什么是库
库文件是计算机上的一类文件,可以将其看为是一种代码仓库,提供一些可以直接使用的变量、函数或者类等。
库文件分为静态库和动态库(共享库)两种,库不能单独运行,需要依赖于可执行文件。
接下来就介绍一下这两种库。
静态库
- 静态库的命名规则
Linux: libxxx.a
lib为库的前缀
xxx为库的名称,由自己起
.a为哭的后缀
Windows: libxxx.lib - 静态库的制作
首先通过gcc将需要制作为库的.c文件编译为.o目标文件。
然后通过ar命令将.o文件打包至库中。
ar命令需要采用rcs的参数,r代表将文件插入备存文件(libxxx.a)中,c代表建立备存文件,s代表索引。
如:
gcc -c xxx.c xxx.c xxx.c #将文件编译
ar rcs libxxx.a xxx.o xxx.o xx.o #使用ar命令将其打包至静态库libxxx.a中
- 静态库的使用
待静态库制作完成后,我们即可使用gcc编译main.c生成可执行文件,但是如果不添加任何参数,会发现其无法找到之前库文件中函数等的引用。
这时,我们在编译时就需要添加参数-l 以及 -L,l代表库的名称,参数后边写上库名称(注意是xxx,而不是libxxx.a),L代表库地址,写上路径即可。
gcc main.c -o app -l xxx -L ./ #./仅代表当前路径,如果你的库存在于其他地方,写上其路径即可
动态库
- 动态库的命名规则
Linux: libxxx.so
lib为库的前缀
xxx为库的名称,由自己起
.so为哭的后缀
Windows: libxxx.dll - 动态库的制作
首先通过gcc将需要制作为库的.c文件编译为.o目标文件。但是这里我们需要使用-fpic参数来使其生成与位置无关的代码。
然后再通过gcc与-shared参数来生成库文件。
当然,这两部可以一步完成。
如:
gcc -c -fpic xxx.c xxx.c
gcc -shared xxx.o xxx.o libxxx.so
或
gcc -shared -fpic -o libxxx.so xxx.c xxx.c
- 动态库的使用
这时,我们在编译时就需要添加参数-l 以及 -L,l代表库的名称,参数后边写上库名称(注意是xxx,而不是libxxx.a),L代表库地址,写上路径即可。**
但在编译完成后,我们执行时会发现,其无法找到这个库。 - 动态库加载失败原因和处理
因为动态库的加载是动态的,并不像是静态库那样,在编译时就加入到可执行文件中,动态库是在可执行文件运行时,将动态库加入到内存中供可执行文件进行使用,多个文件可以同时使用内存中的这个库,这也是其别称共享库的原因。
当我们运行可执行文件时,它会按照下面这个顺序去寻找这个库的地址。
elf文件的DT_RPATH段
环境变量LD_LIBRARY_PATH
/etc/ld.so.cache文件列表
/lib/或/usr/lib目录
所以我们可以通过修改这些地方来使其可以寻找到库文件。
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH: 库文件的绝对路径
#:代表拼接
或
vim ~/.bashrc
然后在其末尾添加export那行代码,保存并退出后,使用下面这个代码使其生效
source ~/.bashrc
上面那种只对单个终端有效,重新打开一个终端就无法生效了,所以我们可以采用下面这个解决办法
sudo vim /etc/profile
然后在末尾添加
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH: 库文件的绝对路径
保存并退出后使其生效
source /etc/profile
也可以
sudo vim /etc/ld.so.conf
添加库文件的绝对路径即可,保存退出后使其生效
source /etc/ld.so.conf
最后一种方法,是将自己的库文件放入/lib/或/usr/lib目录中,但是我们进入到这两个目录中,可以发现有很多系统的库文件,如果我们将自己写的放入,重名替换后就会出现许多问题。
静态库与动态库
- 静态库的优缺点
优点: 静态库被打包到应用程序中加载速度快,并且发布程序无需提供静态库,移植方便。
缺点: 消耗系统资源,浪费内存,更新、部署、发布麻烦。因为其是直接打包到程序中,所以其占用内存与程序绑定,每个使用这个库的文件都会占用这个库大小的内存。 - 动态库的优缺点
优点: 可以实现进程间的资源共享(共享库),更新、部署、发布简单,还可以控制何时加载动态库。动态库是在可执行文件运行时,将动态库加入到内存中供可执行文件进行使用,多个文件可以同时使用内存中的这个库,这也是其别称共享库的原因。
缺点: 加载速度比静态库慢,发布程序时需要提供所依赖的动态库。
静态库适用于小型库,而动态库更适合大型库。