Linux下的静态库和动态库

在我们平时写代码的时候,通常会引用一些库文件来帮助我们实现需要的功能,这些库文件是别人提前已经写好的,我们只需要拿出库文件的接口来使用就可以了。

这种库文件分为两种,一种是静态库,一种是动态库。

静态库(.a):程序在编译链接的时候把库的代码放进可执行文件中。程序运行的时候将不在需要静态库。它的后缀名是一般起名为.a文件。

静态库可以简单的看成一组目标文件集合,即很多目标文件经过压缩打包后形成一个文件。

在静态库的加载过程中,第一步是用编译器进行编译,将我们的源程序编译成一个临时汇编文件,然后用汇编器汇编成临时目标文件,接着最关键的一步,就是链接,这一步会完成对目标文件的链接,我们的静态库就是在这一步被加载进去的,链接器会对链接结果进行一些处理,如我们链接的库文件还会依赖于别的文件,这个时候链接器就会继续链接,收集所有与程序初始化相关的信息别去构造初始化结构。

这些步骤综合起来其实相当复杂,所以会有专业的人员去搞编译这一部分的内容,我们在一开始的时候不必过分深入的研究这一部分的内容,只需要大致知道它的执行过程。

当然,我们需要知道如何去制作静态库:ar -cr libmymath.a file.o file.o,其中ar是gnu的归档工具,cr表示(create and replcce),libmymath.a是静态库文件名,mymath是静态库名,记得一定不要忘记加lib否则可能会执行出错。

制作完成后就是对静态库的使用,只需要-L 库的路径 -l库名就可以使用自己制作的静态库了。

库搜索路径:
1.从左到右搜索-L指定的目录。
2.由环境变量指定的目录。(LIBRARY_PATH)
3.由系统指定的目录>* /usr/lib>* /usr/local/lib

图中的相关源码:静态库的制作
静态库制作

聊完静态库,我们再说说动态库。

动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用的代码。 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在的目标文件的整个机器码。

在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接。

动态库可以在多个程序间共享,所以动态库链接使得可执行文件更小,节省了磁盘空间,操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。这也是为什么要使用动态库的一部分原因。另外一部分原因是静态链接对程序的更新,部署和发布也会带来很多麻烦。比如你的程序需要更新,如果使用静态库,那么就要将新的程序整个重新发布,比如更新了一个1M的模块,其程序原本大小有20M,那么现在就要给21M全部重新发布。如果通过网络来更新,那么就会变得相当不便,因为服务器可能同时要给成千上万的用户做出更新传输,再比如ATM这样的24小时工作的机器,使用静态链接就必须要关闭机器,而动态链接就可以进行平滑升级,诸如此类的好处,所以动态链接在现在还是非常有用的方式。

听了这么多的好处,我们来了解一下动态库是如何制作的,指令gcc -fPIC -shared -o libmath.so file.c file1.c

接下来还必须有一步,指定动态库的路径/etc/ld.so.conf.d/name.conf

因为动态库的动态链接的,所以系统必须刷新过后才能使用,重启可以进行刷新,或者使用命令ldconfig刷新内核缓存,立即生效。

使用动态库:gcc -file.c -L . -lmymath。

通过ldd a.out查看所依赖的库文件路径。

其源码与静态库相比基本没有变化:动态库源码
动态库的使用

猜你喜欢

转载自blog.csdn.net/zym1348010959/article/details/80649852