一、动态库的命名规则
1. Linux:libxxx.so
- lib:前缀(固定)
- xxx:库的名字,自己起
- .so:后缀(固定)
- 在Linux下是一个可执行文件
2. Windows:libxxx.dll
二、动态库(又称共享库,是可执行文件)的制作:
1. gcc 得到.o文件,得到和位置无关的代码
gcc -c -fpic/-fPIC a.c b.c(源文件)
2. gcc得到动态库
gcc -shared a.o b.o -o libcalc.so
3. 制作过程如下:
先把环境准备好
得到.o文件后,再去制作动态库
x x x
ps ef :全格式显示所有进程
三、动态库的使用
library 就相当于我们的一个项目:include 下放头文件,lib目录下:将来放库文件,src目录下跟刚才生成动态库的源代码文件是类似的(正式开发的时候,其实是一些其他的源文件),main.c是测试文件;
1. 把刚才生成的动态库放入,lib目录下
2. 要把动态库和头文件都分发“别人 ”才能使用
动态库库文件里面是函数或者说API的具体定义,头文件里面是声明;
所以没有头文件是不能使用的,因为这样就不知道里面有哪些API
但是我们发现,执行./main,报错了,为什么?
报错信息:当加载共享库的时候,libcalc.so动态库文件,不能打开共享的文件,找不到这样的文件或者目录
这就很奇怪了,该给的信息(指定了库的名称以及库的目录),我们不是都给了吗?但是生成的可执行文件在去运行的时候,找不到动态库文件。
在如何解决这个问题之前,我们得先了解动态库具体实现以及加载的原理;
3. 了解动态库具体实现以及加载的原理(工作原理)
(1)静态库与动态库的工作原理
- 静态库(静态库中都是目标/二进制代码):GCC进行链接时,会把静态库中代码打包到可执行程序中;
- 动态库:GCC进行链接时,动态库的代码不会被打包到可执行程序中;(只会把动态库的一些信息放入到可执行程序中【并不会加载动态库的内容到内存中】,所以我们在运行可执行程序时,要是用到了动态库【使用了动态库中的API时,就会查找动态库的绝对路径,找到后加载到内存中】,在可执行程序中是找不到动态库的代码的,所以会报加载动态库失败这个错误)
- 在程序启动之后,应用了动态库(程序要想运行,首先要加载到内存当中,那么使用到了动态库的内容,就得把动态库的内容一起加载到内存中),就得把动态库先加载到内存中,才能使用;
- 通过ldd(lsit dynamic dependencies 列出动态依赖)命令检查动态库依赖关系;
(2)可执行程序运行起来是怎么去找这些动态库的?
- 如何定位共享库文件呢?
- 当系统加载可执行代码时,能够知道其所依赖的库的名字,但是还是需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径(加载的时机:当我们的程序调用了动态库的一些API时,那就会去加载。)。对于elf格式的可执行程序,是由ld-linux.so(动态载入器)来完成的(来获取动态库的绝对路径,是有先后顺序的),它先后搜索elf文件的DT_RPATH段(我们一个程序运行起来就是一个进程,Linux会为每个进程分配虚拟地址空间,而这个DT_RPATH段是在虚拟地址空间中,若我们没有动态库的路径放进去DT_RPATH段填充的话,是找不到的,而这个DT_RPATH段我们也修改不了,若是找不到,接着我们看下一个)->环境变量LD_LIBRARY_PATH(若是这个环境变量配置了动态库的完整路径的话,动态载入器就会根据这个路径,将动态库完整的加载到内存中,若没有的话,接着往后面找)->/etc/ld.so.cache文件列表->/lib/或者/usr/lib目录找到库文件后将其(动态库内容)载入内存。
4. 解决动态库加载失败问题
(1)方法一:export添加环境变量
方法一:export添加环境变量
这个时候就能查找到了
执行也不报错了
但是,方法一,这种方式有一个弊端,当我们关闭当前连接,再次打开一个终端后,再去执行./main就会报错了,原因是因为,刚才配置的环境变量是在终端去配置的,当我们关闭这个终端,重新打开一个终端后,这个环境变量就消失了(临时);所以我们应该永久的去配置这个环境变量。(用户级别的配置和系统级别的配置)
(2)方法二:用户级别的配置
step one : 先进入home目录下;
step two : vim .bashrc
step three : 拼接上我们创建的动态库的绝对路径
step four : 保存退出后,要使刚才的配置生效
两种语句:. .bashrc;或者source .bashrc
step five : 执行./main
(3)方法三:系统级别的配置
先把之前用户级别的配置删掉再重新生效
step one : sudo vim /etc/profile【sudo … 提权】
配置
step two : source /etc/profile
(4)方法四:修改/etc/ld.so.cache文件列表
首先,还是先清除刚才的配置,不然看不出效果;注意注意,要是感觉删除配置取消不了影响,就试一下生效source完之后,重新连接虚拟机,再打开一个窗口;
one : ll /etc/ld.so.cache (先观察一下)
two : vim /etc/ld.so.cache【它里面都是二进制的数据,不允许编辑,所以我们不能直接修改它,而是间接修改它】
three : sudo vim /etc/ld.so.conf,然后在这个文件中加入路径
four : 进行配置的更新:sudo ldconfig
生效完就可以找到了;