目录
1 动态库概念
与静态库区别
静态库中函数生成的目标代码直接嵌入了最终的目标文件中,而动态库是在用到库中函数的时候才临时把动态库文件加载到进程虚拟地址空间中的共享库区域。如下图所示,在用户区栈和堆之间。
静态库名字一般是 libXXXX.a
动态库名字一般是 libXXXX.so
位置无关概念
如果要使用动态库中某个函数,当把动态库加载到地址空间中共享库区域之后,先找到了这个库,然后根据函数的入口地址距离这个库的地址的偏移,即可找到要使用的函数,这种用相对位置找到函数入口的方式就称为位置无关。
在制作动态库的时候,源材料文件变成成 .o文件的时候要指定编译成位置无关的,具体就是编译时加上 -fPIC选项。
2 动态库制作
与静态库制作一样(静态库制作与使用_chk_plusplus的博客-优快云博客),还是以计算器制作为例子。
第一步:将源文件编译成位置无关 .o文件,其中include是头文件目录
gcc -fPIC -c *c -I ../include
第二步:根据源文件生成库文件,指定shared选项
注意要指定文字需要加上-o选项,否则自动命名a.out,因为静态库是用ar rcs打包的,因此不存在这个问题。
gcc -shared -o libCalc.so *.o
第三步:使用动态库生成目标文件
gcc main.c -o newapp -I ./include -L ./lib -l Calc
目录组织如下
3 动态库使用
随上在2中我们通过指定动态库路径和头文件的情况下生成了可执行目标文件,但是在运行的时候是没办法运行的,因为动态库的特点就是库中函数生成的目标代码并没有嵌入最终目标文件,所以在运行的时候还要链接动态库,即运行的时候也要能找到动态库才行。
可以用 ldd newapp的方式查看可执行问及那newapp用到的动态库
红色下划线是我们自己的动态库,可以看到在运行的时候没有找到
有三种解决方案给运行阶段指定动态库。
解决方案一:/lib与/usr/lib目录
因为/lib和/usr/lib是系统存放动态库的目录,可以直接把动态库存放到这两个目录下,这两个目录应该在LD_LIBRARY_PATH这个环境变量里(额这个错了,经验证并不是,直接原因就是这来两个目录是linux系统用来存放动态库的目录),因此程序运行的时候是可以找到的。
也可以用软硬链接,将链接放入这两个目录。
软链接注意事项:不要用相对地址来创建软链接,因为一旦原文件或者链接文件移动目录,软链接就失效了。所以要用绝对地址。
硬链接当然是完全没有问题的。
解决方案二:环境变量LD_LIBRAR_PATH
将库路径增加到环境变量LD_LIBRARY_PATH中去,因为ld链接器在找动态库路径的时候实际上会从这个环境变量包含的路径中搜索。
查看环境变量的值
echo $LD_LIBRARY_PATH
用export在终端配置环境变量,一旦终端退出则配置失效,因此要配置到.bashrc文件中,因为linux系统开机时会执行一遍里边的指令。
export LD_LIBRARY_PAHT=val
解决方案三 /etc/ld.so.conf
把动态库的路径加入到链接器的这个配置文件/etc/ld.so.conf中,这个是推荐使用的方法。
这种方法要使用root权限,
写入库路径之后配置还没有生效,执行
sudo ldconfig -v命令来让配置生效,然后系统就可以正常使用动态库了。
4 动态库优缺点
缺点:
执行时需要加载动态库,比静态库慢
发布应用时要同时发布动态库,否则该应用无法执行
优点:
生成可执行目标文件体积更小
库变更时,只要使用到的接口及其功能没变,不用重新编译应用