【Linux系统化学习】动静态库 | 软硬链接
目录
硬链接和软链接
硬链接
软链接
动态库和静态库
静态库
静态库的生成
静态库的使用
将库打包和使用
动态库
动态库的生成
动态库的使用
库搜索路径
硬链接和软链接
硬链接
上篇文章我们说到真正找到磁盘上的文件并不是文件名,而是inode。其实在Linux中可以让多个文件名对应同一个inode,这样的方式就是硬链接。
指令:ln
总结:
硬链接不是一个独立的文件 ,就是在指定目录内部的一组映射关系。相当于引用计数;当没有文件名和inode映射时表示该文件被真正的删除。
硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。
注:硬链接只可以链接文件不可以链接目录;因为引入了对目录的硬连接就有可能在目录中引入循环,在目录遍历的时候系统就会陷入无限循环当中,这样导致无法定位到访问目录。但是我们的Linux系统可以硬链接目录;每个目录文件中含有两个隐藏文件,分别为当前目录和上级目录,当前目录隐藏文件就和当前目录硬链接。
软链接
硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件。
指令:ln -s
总结:
软连接是一个独立的文件,有独立的inode;软连接内容时指向目标文件的路径,类似于Windows的快捷方式。
动态库和静态库
在之前的文章中我们提到过系统库,当时只是简单的讲解了下静态库和动态库的优缺点;这篇文章我们要从一个库的制作者和使用者来详细介绍第三方库的制作和使用。
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚
- 拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
静态库
我们以一个库的制作者的角度自己编写一个可以实现整数加减的库;就是将实现整数加减的两个函数声明和定义分开,声明放在头文件中,实现放在源文件中。
头文件
1 #pragma once 2 #include<stdio.h> 3 extern int Add(int,int);
1 #pragma once 2 #include<stdio.h> 3 extern int Sub(int,int);
源文件
1 #include"Add.h"2 int Add(int x,int y)3 {4 return x+y; 5 }
1 #include"Sub.h"2 int Sub(int x,int y)3 {4 return x-y; 5 }
当我们以库的制作者的身份将库写好后;我们就以普通程序员的身份使用这个库编写简单的程序。
1 #include"Add.h"2 #include"Sub.h"3 int main()4 {5 int x =10;6 int y=20;7 printf("%d + %d = %d\n",x,y,Add(x,y));8 printf("%d - %d = %d\n",x,y,Sub(x,y)); 9 return 0;10 }
第一种使用方法就是将我们自己编写的源代码和库的源代码一起编译链接形成一个可执行程序即可。
但是这种使用方法我们要拿到库的源代码;再将库的每个源代码和我们的源代码一起预处理、编译、链接形成可执行程序。对于我们这种小库可能没什么影响,对于一些大的库源文件很多,每个源文件都进行这三部操作的话,很是浪费时间。
静态库的生成
对于上面的问题我们可以很好的解决;不是库的源文件浪费时间么,同时作为库的制作者我们也不想将我们的源代码公开,那我们可以将我们的库先编译成为二进制文件(.O)文件,将二进制文件和库使用者的二进制文件进行连接即可形成可执行程序。
makefile1 test:Add.o Sub.o testmain.o2 gcc -o $@ $^3 %.o:%.c4 gcc -c $<
但是当我们库很大源文件很多时,形成的二进制文件也特别多;要是我们给库使用者二进制文件少给一个呢?
当我们想要这个库时候是不是只需要将我们的源文件编译成.o文件和库文件进行链接即可。因此我们可以将库的源文件编译成.o文件打包交给程序员即可。
makefile static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3 ar -rc $@ $^ 6 %.o:%.c7 gcc -c $<8 .PHONY:clean9 clean:10 rm -rf *.o test
指令:ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
当我们库的源文件很多时,我们可以使用makefile,将我们的源代码自动生成二进制文件,再将我们的二进制文件全部形成我们的静态库。这里我们库的源文件很少,我就直接给大家手动生成。
通过上面的操作我们就可以将库的源文件生成二进制文件,进行生成静态库。
静态库的使用
将生成好的二进制文件和头文件拷贝到,我们的使用者编写的源代码下就可以使用库了。但是我们在使用静态库时还有很多小细节要注意。
将静态库和我们的源文件进行链接时首先要表用链接库的名称,和静态库的路径。其中库的名称是去掉后缀(.a)和lib。
- -l 静态库的名称 代表我们链接哪一个静态库
- -L 路径 代表所要链接静态库的所在路径
将库打包和使用
上面只是进行了二进制文件的打包当我们库源文件很多时,头文件也很多;因此我们可以将头文件和二进制文件分开存储在一个目录中打包交给使用的程序员。这里我们就不打包了,我们只将其放在同一个目录中使用。
static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3 ar -rc $@ $^6 %.o:%.c7 gcc -c $<8 .PHONY:output9 output:10 mkdir -p mymath_lib/include11 mkdir -p mymath_lib/lib 12 cp -f *.h mymath_lib/include13 cp -f *.a mymath_lib/lib14 .PHONY:clean15 clean:16 rm -rf *.o test mymath_lib
但是打包好的头文件和二进制文件在统一目录下,而我们的源文件并不在统一目录下,因此我们在使用的时候还要加上一些选项。
注:头文件的查找在当前目录下或者指定目录下查找,因此我们加上头文件的路径。
-I 头文件路径
动态库
动态库的生成
动态库也是将所有的的源文件形成二进制文件文件生成的;但是和动态库的生成方式和使用方式略有差异。
注意:动态库的生成是使用gcc编译器来完成的,因此比较重要
makefile1 dy-lib=libmymath.so 2 $(dy-lib):Add.o Sub.o3 gcc -shared -o $@ $^4 %.o:%.c5 gcc -fPIC -c $<6 .PHONY:output7 output:8 mkdir -p mymath_lib/include9 mkdir -p mymath_lib/lib 10 cp -f *.h mymath_lib/include11 cp -f *.a mymath_lib/lib12 .PHONY:clean13 clean:14 rm -rf *.o *.so mymath_lib
~
- shared: 表示生成共享库格式
- fPIC:产生位置无关码(position independent code)
- 库名规则:libxxx.so
有了上面静态库的生成,静态库的生成我们就不过多赘述,只是生成动态库执行的选项不一样而已。
动态库的使用
动态库的使用也是有很多的小细节,使用不当也会产生找不到动态库或者找不到头文件的问题。
就像下面我们直接使用使用静态库的方法使用动态库,系统还是找不到我们的库在哪里。
原因:
静态库是直接和我们的可执行程序链接在一起的,在连接的时候告诉我们的编译器我们库的路径编译器就可以找到。但是对于动态库不是链接在可执行程序中,可执行程序和库必须都加载到内存中,我们告诉了gcc编译器我们的库在哪里,但是操作系统要将我们的库加载到内存中,操作系统却不知道我们的库在哪里,系统默认找不到。因此我们要解决系统找不到我们库的问题。
库搜索路径
方法一:将头文件和库文件安装到系统中
- /usr/include
- /lib64
在我们这两个系统路径下分别存放着库的头文件和二进制文件,我们可以将我们的二进制文件和头文件分别拷贝到上面的系统路径下即可。
方法二:建立一个软链接
在生成可执行程序的目录下建立一个库的软链接即可。
方法三:修改环境变量
LD_LIBRARY_PATH
执行我们的可执行程序系统不仅会在指定的路径下寻找我们的动态库,还会在一个环境变量中寻找。Linux中存在这样一个环境变量记录着动态库的存储路径。我们可以将我们的动态库添加到这一环境变量中即可。
注意:
当我们退出我们的云服务器,重新登录后添加的环境变量就将会重置。
方法四:更改配置文件
Linux下含有一个文件夹其中包含有关动态库加载的配置文件,里面只含有一个路径。我们可以在其目录下创建一个相同格式的空白文件,再将我们库的路径填入其中保存即可。
今天对Linux下动静态库的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!
相关文章:

【Linux系统化学习】动静态库 | 软硬链接
目录 硬链接和软链接 硬链接 软链接 动态库和静态库 静态库 静态库的生成 静态库的使用 将库打包和使用 动态库 动态库的生成 动态库的使用 库搜索路径 硬链接和软链接 硬链接 上篇文章我们说到真正找到磁盘上的文件并不是文件名,而是inode。其实在…...

linux-firewalld防火墙端口转发
目的:通过统一地址实现对外同一地址暴露 1.系统配置文件开启 ipv4 端口转发 echo "net.ipv4.ip_forward 1" >> /etc/sysctl.confsysctl -p 2.查看防火墙配置端口转发之前的状态 firewall-cmd --statefirewall-cmd --list-all 3.开启 IP 伪装 firewall-cm…...

adobe软件提示This non-genuine Adobe app will be disabled soon【软件版本】
因为电脑上级路由器装了小飞机,导致本机电脑ps等adobe的系列软件出现了 This non-genuine Adobe app will be disabled soon,烦人的狠,之前有写过一篇通过更改host的教程,现在已经失效了,今天为大家分享一个用软件来屏…...

python coding with ChatGPT 打卡第20天| 二叉搜索树:搜索、验证、最小绝对差、众数
相关推荐 python coding with ChatGPT 打卡第12天| 二叉树:理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树:翻转…...

Stable Diffusion——基础模型、VAE、LORA、Embedding各个模型的介绍与使用方法
前言 Stable Diffusion(稳定扩散)是一种生成模型,基于扩散过程来生成高质量的图像。它通过一个渐进过程,从一个简单的噪声开始,逐步转变成目标图像,生成高保真度的图像。这个模型的基础版本是基于扩散过程…...

Python自动化部署与配置管理:Ansible与Docker
Ansible 和 Docker 是两种常用于自动化部署和配置管理的工具。Ansible 是一个基于 Python 的自动化运维工具,可以配置管理、应用部署、任务自动化等。而 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&…...

《摔跤吧爸爸》19岁女星突患皮肌炎离世
从确诊到离世仅10天……罕见病“皮肌炎”! 曾凭借在知名电影《摔跤吧!爸爸》中饰演童年时期“小芭比塔”一角而广受喜爱的年轻演员苏哈尼巴特纳格尔不幸离世,年仅19岁。她的突然逝世引发了全球关注,据苏哈妮的家人表示࿰…...

用结构体数组,完成宠物信息登记管理。
管理宠物的名字,品种,年龄。 实现功能如下: 1.插入宠物信息 2.遍历宠物信息 #include <stdio.h> #define N 100 typedef struct chongwu { char name[20]; char pingz[10]; int age; }cw; void intset_cw(cw *ptr,int *pnum) { printf("请…...

频率主义线性回归和贝叶斯线性回归
整体概述 频率主义(Frequentist)线性回归和贝叶斯(Bayesian)线性回归是统计学中用于数据分析和预测的两种主要方法,特别是在建模关于因变量和自变量之间线性关系的上下文中。尽管两种方法都用于线性回归分析ÿ…...

【感知算法】Dempster-Shafer理论(下)
尝试DS理论应用到自动驾驶地图众包更新。 地图特征变化判断 a mass function is applied to quantify the evidence of the existence. existence state: existenct、non-existent、tenative、conflict ∃ ∄ Ω ϕ \exist \\ \not\exist \\ \Omega \\ \phi ∃∃Ωϕ ma…...

通过conda安装cudatoolikit和cudnn
通过conda安装cudatoolikit和cudnn 安装cudatoolkit安装cudnn安装cudatoolkit-dev 安装cudatoolkit conda install cudatoolkit11.3 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ 安装cudnn conda install cudnn8.5 -c https://mirrors.tuna.tsinghua.edu.…...

vue中使用jsx语法
请注意,在 Vue 中使用 JSX 时,你仍然需要通过 h 函数(通常是一个别名,对应于 createElement 函数)来创建虚拟 DOM 元素。在下面的例子中,h 函数作为 render 函数的参数传入,但在 JSX 语法中你通…...

我的NPI项目之Android USB 系列(一) - 遥望和USB的相识
和USB应该是老朋友了,从2011年接触Android开发开始,就天天和USB打交道了。那时候还有不 对称扁头的usb/方口的usb,直到如今使用广泛的防反插USB3.0 type-C。 但是,一直有一个不是很清楚的问题萦绕在心头,那就是。先有…...

K8s进阶之路-命名空间级-服务发现 :
服务发现: Service(东西流量):集群内网络通信、负载均衡(四层负载)内部跨节点,节点与节点之间的通信,以及pod与pod之间的通信,用Service暴露端口即可实现 Ingress&#…...

智慧公厕管理系统:让城市智慧驿站更加智慧舒适
智慧公厕管理系统是城市智慧驿站中不可或缺的一部分,它通过全方位的信息化解决方案,为公共厕所的使用、运营和管理提供了一种智能化的方式。作为城市智慧驿站的重要组成部分,智慧公厕管理系统发挥着重要的作用,为城市社会民生提供…...

图形渲染基础学习
原文链接:游戏开发入门(三)图形渲染_如果一个面只有三个像素进行渲染可以理解为是定点渲染吗?-CSDN博客 游戏开发入门(三)图形渲染笔记: 渲染一般分为离线渲染与实时渲染,游戏中我们用的都是…...

每日学习总结20240219
每日总结 20240219 1.文件类型.csv CSV文件是一种以逗号分隔值(Comma-Separated Values)为标记的文本文件,它可以用来存储表格数据。每一行表示一条记录,而每一条记录中的字段则使用逗号或其他特定的分隔符进行分隔。 常用场景…...

K8s进阶之路-安装部署K8s
参考:(部署过程参考的下面红色字体文档链接就可以,步骤很详细,重点部分在下面做了标注) 安装部署K8S集群文档: 使用kubeadm方式搭建K8S集群 GitBook 本机: master:10.0.0.13 maste…...

springboot集成elk实现日志采集可视化
一、安装ELK 安装ELK组件请参考我这篇博客:windows下安装ELK(踩坑记录)_windows上安装elk教程-CSDN博客 这里不再重复赘述。 二、编写logstash配置 ELK组件均安装好并成功启动,进入到logstash组件下的config文件夹,创建logstash.conf配置…...

leetcode 148. 排序链表 java解法
Problem: 148. 排序链表 思路 这是一个链表排序的问题,由于要求时间复杂度为 O(nlogn),适合使用归并排序(Merge Sort)来解决。 解题方法 首先,使用快慢指针找到链表的中间节点,将链表分成两部分。然后&…...

【MATLAB源码-第140期】基于matlab的深度学习的两用户NOMA-OFDM系统信道估计仿真,对比LS,MMSE,ML。
操作环境: MATLAB 2022a 1、算法描述 深度学习技术在无线通信领域的应用越来越广泛,特别是在非正交多址接入(NOMA)和正交频分复用(OFDM)系统中,深度学习技术被用来提高信道估计的性能和效率。…...

运动重定向学习笔记
目录 深度学习 重定向 2020年的模型: 重定向之后的bvh: 深度学习 重定向 输入是bvh,输出也是bvh...

导出Excel,支持最佳
列表信息导出为Excel文件, 依赖pom: Sheet, Row:<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId> </dependency>XSSFWorkbook <dependency><groupId>org.apache.poi</…...

【WPF】获取父控件数据
MaxHeight"{Binding PathActualHeight, RelativeSource{RelativeSource ModeFindAncestor, AncestorTypeUserControl}}" 参考文献 https://www.cnblogs.com/-Timosthetic/p/16021865.html...

解决Edge浏览器,微博无法查看大图(Edge Image Viewer)
使用Edge浏览器浏览微博或其它带校验的图片时,会导致无法查看。 主要原因为Edge自带了一个Edge Image Viewer, 但是该图片查看器无法查看带校验数据的图片,所以导致查看时一片空白。 解决方法 地址栏输入 edge://flags/搜索 Edge Image Viewer选择 Disa…...

PMP含金量在国内怎么样?
其一、PMP(项目管理师)证书含金量高吗? PMP认证是由美国项目管理学会(PMI)在全球范围内推出的针对项目经理的资格认证体系,其证书含金量可以说是非常高。 统计表明,全球年销售收入在5亿美元以上的企业中有86%聘用了具有项目管理资质的项目经…...

java中容易被忽视的toString()方法
之前一直认为toString就是将数据转换成字符类型,直到最近写出了一个bug才对toString有了新的认识 不同数据类型,toString() 有不同的操作 定义一个student类,包含姓名 String类型、性别 String类型、年龄 int 类型、分数列表 String类型的li…...

如何使用Docker搭建YesPlayMusic网易云音乐播放器并发布至公网访问
文章目录 1. 安装Docker2. 本地安装部署YesPlayMusic3. 安装cpolar内网穿透4. 固定YesPlayMusic公网地址 本篇文章讲解如何使用Docker搭建YesPlayMusic网易云音乐播放器,并且结合cpolar内网穿透实现公网访问音乐播放器。 YesPlayMusic是一款优秀的个人音乐播放器&am…...

java面试题之redis篇
1.redis 中的数据类型有哪些 随着 Redis 版本的更新,后面又支持了四种数据类型: BitMap(2.2 版新增)、HyperLogLog(2.8 版新增)、GEO(3.2 版新增)、Stream(5.0 版新增&am…...

effective c++ 笔记 条款18-25
条款18:让接口容易被正确使用,不易误使用 使用外覆类型(wrapper)提醒调用者传参错误检查,将参数的附加条件限制在类型本身 Data::Data(int month, int day, int year) { ... }三个参数类型相同的函数容易造成误用 Da…...