动态库和静态库
静态库与动态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候不再需要静态库。
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态链接的可执行文件仅仅包含他用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程公用,节省了内存和磁盘空间。
一般云服务器,默认只会存在动态库,静态库需要单独安装。
静态库
作为库的分享者
现在我们分别建立下面几个文件,并编写程序。
现在为了模拟其他人来使用我们自己打包好的库的动作,我们把这些文件分别放到了mylib和otherPerson里
如果我们不想要其他人看到我们程序具体方法的实现,我们可以交付我们编译好的.o和.h文件,让对方在知晓我们方法的前提下,又实现了保密。
执行gcc -c,完成预处理、编译、汇编生成可重定位二进制目标文件(.o文件)。
把.h和.o文件都复制到otherPerson文件夹
首先编译自己的main.c
然后一起链接
可以看到最后我们就在没有.c文件的otherPerson文件夹里成功调用了我们自己编写的myadd和mysub文件并运行。
然后我们将生成的.o文件打一个包。(前缀lib,后缀.a,但是真实名字是·mymath)
那么如何使用呢?
作为库的使用者
第三方库的使用
1、需要指定的头文件和库文件
2、如果没有默认安装到系统gcc,g++默认的搜索路径下,用户必须指明对应的选项,告知编译器:a、头文件在哪里 b、库文件在哪里 c、库文件名字。
3、将我们下载下来的库和头文件,拷贝到系统默认路径下–在Linux下安装库!
4、如果我们安装的库是第三方的(第一方:语言、第二方:操作系统接口),我们要正常使用,即使是已经全部安装到了系统中,gcc/g++必须用-l来指明具体库的名称!
__方法一:__没有默认安装到系统gcc,g++默认的搜索路径下,用户必须指明对应的选项,告知编译器:a、头文件在哪里 b、库文件在哪里 c、库文件名字。
gcc -选项
-L 指定库路径
-l 指定链接的库名
我们可以看到上图在只有.h 和静态库的情况下,我们仍然成功运行了程序。
现在我们来真实模拟一下,在网络上下载了压缩文件之后该怎么使用。
1、解包
2、编译
对任何软件而言,安装和卸载的本质就是拷贝到系统特定的路径下
但是回想一下,我们以前在c/c++语言学习过程中对标准库(比如stdio)的调用。对比起来是不是我们自制的库的使用过程还是比较繁琐。所以我们进一步进行下一步操作,不需要我们自己指明搜索路径,只要我们将我们的库文件以及头文件拷贝到库默认的搜索路径下即可。
__方法二:__没有默认安装到系统,通过复制将文件安装到搜索路径下
然后直接gcc,成功运行。
动态库
shared:表示生成共享库格式
fPIC:产生位置无关码(position independent code)
库名规则:libxxx.so
作为库的分享者
1、预处理、汇编、编译生成.o文件和位置无关码
2、将.o文件打包生成.so
3、压缩并上传
作为库的使用者
1、解包
2、编译
然后按照静态库的使用方法直接编译,会发现我们即便是在指定了头文件路径,库路径,库名称之后仍然无法成功链接。那么就不得不提到静态库和动态库的区别了。
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候不再需要静态库。
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
我们使用ldd来打印程序或者库文件所依赖的共享库列表。
3、运行
临时
可以发现动态库not found。所以接下来我们需要让系统能够搜索到我们的动态库。
此时我们就可以找到动态库,然后运行程序了。
我们这种方法是临时修改了环境变量,当我们再次进入时候,配置文件里还是没有,所以是临时的
永久–软连接
通过在系统中指定的系统路径下建立软链接指向我们的库,系统就可以直接加载我们的库了。
由于软连接是一个正常的、在磁盘上可以永久存在的文件,当我们重新登录的时候,仍然存在,所以是永久的
永久–配置文件
1、在/etc/ld.so.conf.d/路径下创建maria.conf文件,其文件内容为动态库所在的绝对路径(即 /home/mr/lesson19/otherPerson/lib/)
2、执行ldconfig(需要sudo提权),更新
动态库必定面临一个问题:不同的进程,运行程度不同,需要使用的第三方库是不同的。注定了,每一个进程的共享空间中的空闲位置是不确定的。所以动态库中的地址绝对不能使用绝对编址。都是偏移量。(位置无关码)
注意:
1、编译器,在链接的时候,如果提供的库既有动又有静,优先动;只有静,只能静
2、动态库和静态库同时存在,系统默认采用动态链接
3、 云服务器一般只会提供动态库。
最后祝我生日快乐❤