Linux基础(8):Linux中静态库和动态库
静态库和动态库的制作、 使用、 处理动态库链接问题等
库文件,简单说就是源文件(.c/.cpp)转换为二进制文件。
采用库文件的目的
- 简化工程的源文件数量,生成库文件之后是不需要再去维护的。
- 开发者处于保护知识产权的目的
拥有库文件之后,同时还要有库的API声明(头文件),添加头文件到项目中,使用其API
静态库
静态库的生成
- 生成汇编文件
1
2#得到-o的汇编文件
gao@gao-VirtualBox:~/桌面/test/d$ gcc -c add.c sub.c- 打包汇编文件
1
2#rcs参数必须带,库的命名遵循libXXX.a的规则
gao@gao-VirtualBox:~/桌面/test/d$ ar rcs libcal.a add.o sub.o- 将声明文件和库文件放在一起
此示例中,是将head.h和libcal.a文件共同发布给使用者
操作示例
1 | #准备相关文件,head.h add.c sub.c main.c |
静态库的使用
- 关键语法
1
2
3#gcc命令下指定库文件地址, 指定库文件名称(名称掐头去尾)
gao@gao-VirtualBox:~/桌面/test/e$ gcc main.c -o cal -L ./ -l cal
# -L指定搜索库的路径, -l指定库的名称操作示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#将发布的静态库文件和头文件放在一个文件夹中,再放入需要执行的程序main.c
gao@gao-VirtualBox:~/桌面/test/e$ ls
head.h libcal.a main.c
#尝试直接编译程序,会报找不到函数实现的错误
gao@gao-VirtualBox:~/桌面/test/e$ gcc main.c -o cal
/usr/bin/ld: /tmp/ccTynhSq.o: in function `main':
main.c:(.text+0x25): undefined reference to `add'
/usr/bin/ld: main.c:(.text+0x47): undefined reference to `sub'
collect2: error: ld returned 1 exit status
#gcc命令下指定库文件地址, 指定库文件名称(名称掐头去尾)
gao@gao-VirtualBox:~/桌面/test/e$ gcc main.c -o cal -L ./ -l cal
gao@gao-VirtualBox:~/桌面/test/e$ ls
cal head.h libcal.a main.c
#顺利生成并执行
gao@gao-VirtualBox:~/桌面/test/e$ ./cal
a+b=20
a-b=0
动态库
动态库的制作&发布
基本语法
同静态库一样,依然是先准备需要发布的文件
之后执行汇编,再进行打包操作
关键点
汇编时加入-fpic参数,表明与位置无关,之后才能进一步生成动态库
打包时,-shared参数,表明是动态库类型
linux下动态库,统一格式libXXX.so
1
2
3
4
5#汇编命令
gao@gao-VirtualBox:~/桌面/test/f/d$ gcc -c -fpic add.c sub.c
#打包操作
gao@gao-VirtualBox:~/桌面/test/f/d$ gcc -shared add.o sub.o -o -libcal.so操作示例
1
2
3
4
5
6
7
8
9
10gao@gao-VirtualBox:~/桌面/test/f/d$ ls
add.c head.h main.c sub.c
#执行汇编后
gao@gao-VirtualBox:~/桌面/test/f/d$ gcc -c -fpic add.c sub.c
gao@gao-VirtualBox:~/桌面/test/f/d$ ls
add.c add.o head.h main.c sub.c sub.o
#执行打包操作后
gao@gao-VirtualBox:~/桌面/test/f/d$ gcc -shared add.o sub.o -o -libcal.so
gao@gao-VirtualBox:~/桌面/test/f/d$ ls
add.c add.o head.h libcal.so main.c sub.c sub.o发布时将head.h和libcal.so两个文件均发布出去.
动态库的调用方式
基本语法
编译使用含有动态库的文件时,同静态库类似,需要指明库的路径以及名称
1
2
3
4
5
6
7gao@gao-VirtualBox:~/桌面/test/f/d$ gcc main.c -o cal -L./ -l cal
gao@gao-VirtualBox:~/桌面/test/f/d$ ls
add.c add.o cal head.h libcal.so main.c sub.c sub
#但是实际运行时,动态库会报错
gao@gao-VirtualBox:~/桌面/test/f/d$ ./cal
./cal: error while loading shared libraries: libcal.so: cannot open shared object file: No such file or directory
处理动态库链接不到问题
常用的办法
首先明确,链接时是由动态链接器来寻找库文件,其搜寻路径如下
1 | 1.可执行文件内部的 DT_RPATH 段 |
所以要保证,我们的库文件能在这四个途径之一中被动态链接器找到。
丙哥的文章中(链接附于文末)提供了三种方案,针对2.3.4的途径进行设置,我偷个懒仅以第三种方案为例来进行测试。实际情况中,这种方式较差,软链接要优于该方案,因为软链接在库更新后,是无需变动的,而拷贝方案则需要重新拷贝获得最新库文件。
操作示例
1 | #采用拷贝库文件的方式来解决,面向途径四来修改 |
优缺点
- 静态库
优点
1 | 1.直接封装进程序,无需额外的库文件,移植方便 |
缺点
1 | 1.多个程序之间都利用该静态库时,都要保存一份代码,空间浪费 |
- 动态库
优点
1 | 1.多个文件同时共享,节省空间资源 |
缺点
1 | 1.运行时被加载,速度相较于静态库慢 |