静态库与动态库
1. 函数库
1.本质:一组函数,具有相近的功能或操作同一数据结构
- <string.h>:strcpy/strcmp/strcat/strlen/strstr/strchr/strtkk…..
- 自定义库:<mysort.h>:bubble_sort/select_sort/quick_sort/insert_sort…..
2.作用:
- 代码复用
- 出现积累
3.发布形式:
源码形式
- 优点:方便使用者学习和使用
- 缺点:保密性差、编译程序耗时、编译受平台、版本限制
二进制形式:
- 优点、缺点与上面相反
4.我们使用的函数:标准c库:/lib/x86_64-linux-gnu/libc.so.6`
2.静态库
在linux中静态库由程序ar生成,现在静态库已经不像之前那么普遍了,这主要是由于程序都在使用动态库。关于静态库的命名如下:
- 机制:在编译程序时,复制静态库的代码片,到可执行程序中
- 优点:将函数库中的函数本地化,寻址方便,速度快。(库函数执行效率==自定义函数执行效率)
- 缺点:消耗系统资源大,每个使用静态库的程序,都要复制一份静态库,浪费内除。
- 使用场景:多用于核心程序,保证时效性,可以忽略空间。
- 静态库的命名方式:
- 在Linux中静态库以lib作为前缀,以.a作为后缀,中间是库的名字(自己指定即可),即libxxx.a
- 在Windows中静态库一般以lib作为前缀,以lib作为后缀,中间是库的名字(自己指定即可),即libxxx.lib
2.1生成静态库链接
生成静态库,需要先对源文件进行汇编操作(使用参数-c)得到二进制格式的目标文件(.o格式)。然后再通过ar工具将目标文件打包就可以得到静态库文件了(libxxx.a)。
使用ar工具创建静态库的时候需要三个参数:
参数c:创建一个库,不管库是否存在,都将创建。
参数s:创建目标文件索引,这在创建较大的库时能加快时间。
参数r:在库中插入模块(替换)。默认新的成员添加在库的结尾处,如果模块名已经在库中存在,则替换同名的模块。
2.2静态库的使用
参数-l:在程序编译的时候,指定使用的库(掐头去尾)
参数-L:指定编译的时候,搜索的库的路径———–>空格空不空都可以
步骤:
添加静态库的函数功能实现:分别在add.c、sub.c、mul.c文件中添加各自代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14//add.c文件添加如下代码
int add(int a, int b){
return a+b;
}
//sub.c文件添加如下代码
int sub(int a, int b){
return a-b;
}
//mul.c文件添加如下代码
int mul(int a, int b){
return a*b;
}创建一个调用静态库的函数:在math.c文件中添加如下程序
1
2
3
4
5
6
7
8
9
10
11
int add(int, int);
int sub(int, int);
int mul(int, int);
int main(int argc, char *argv[]){
printf("%d + %d = %d\n", 10, 20, add(10,20));
printf("%d - %d = %d\n", 10, 20, sub(10,20));
printf("%d * %d = %d\n", 10, 20, mul(10,20));
return 0;
}生成静态库:
- 将静态库要实现的功能函数生成二进制文件(.o文件):
gcc -c add.c sub.c mul.c
- 通过二进制文件生成静态库libmymath.a:
ar rs libmymath.a add.o sub.o mul.o
- 将静态库要实现的功能函数生成二进制文件(.o文件):
在编译程序时使用静态库:
gcc math.c -L ./ -lmymath -o app
- 解释:-L参数后面是要使用的静态库位置;-lmymath是静态库的名字(掐头去尾)
2.动态库
动态链接库是程序运行时加载的库,当动态链接库正确部署之后,运行的多个程序可以使用同一个加载到内存中的动态库,因此在Linux中动态链接库也可称之为共享库。
机制:代码共享
优点:节省内存(共享)、易于更新(动态链接)
缺点:相较于静态库而言,函数调用速度慢(函数地址“延时绑定”)
使用场景:
- 对程序执行速度要求不是很强烈,而对系统资源有一定要求的场景
- 更新比较频繁的程序,方式如下:
- 停止运行程序
- 使用新库覆盖旧库(保证新库、旧库名称一致;接口一致)
- 重启程序
动态库的命名方式:
- 在Linux中动态库以lib作为前缀,以.so作为后缀,中间是库的名字(自己指定即可),即libxxx.so
- 在Windows中动态库一般以lib作为前缀,以dll作为后缀,中间是库的名字(自己指定),即libxxx.dll
注意:
- 动态库是否加载到内存,取决于“程序是否运行”
- 动态库加载至内存的位置是不固定的
2.1生成动态链接库
生成动态链接库是直接使用gcc命令并且需要添加-fPIC(-fpic)以及-shread参数
-fPIC或-fpic参数:是使得gcc生成的代码是与位置无关的,也就是使用相对位置。
-shared参数:是告诉编译器生成一个动态链接库
2.2使用步骤
生成与位置无关的目标文件:
gcc -c -fPIC add.c sub.c mul.c
通过目标文件生成动态库:
gcc -shared -o libmymath.so add.o sub.o mul.o
使用动态库生成可执行文件:
gcc math.c -o app -L ./ -lmymath
启动程序:
./app
报错原因:”动态链接器”ld-linux-x86-64.so.2搜索动态库的路径没有指定
- 链接器:工作于gcc生成可执行文件过程中的“链接阶段”,工作结束后,生成可执行文件
- 动态链接器:工作于可执行程序运行之后,辅助加载器负责动态库加载到内存
1
./app: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory
解决上述报错的基本思想:给动态链接器指定动态库路径
环境变量法:
export LD_LIBRARY_PATH=./lib
将当前动态库所在目录,加入到环境变量中- 终端一旦退出,环境变量的修改无效
配置文件法:将上述修改环境变量的指令,写入到~/.bashrc中
- 每次启动终端,自动生效
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib
拷贝法:受程序使用libc库的启发,将自定义的libmymath.so文件拷贝到/lib 或 /user/lib目录中
- 为了执行用户自定义程序,需要修改系统配置
缓存文件法(推荐使用):通过修改配置文件,修改缓存文件,生成动态库连接器需要搜寻的新目录位置
- 1.打开配置文件:
vim /etc/ld.so.conf
- 2.修改配置文件:将动态库的绝对路径添加到
/etc/ld.so.conf
文件中 - 3.使用命令
sudo ldconfig -v
动态更新ld.so.cache文件(二进制文件),该文件直接影响动态连接器搜寻动态库位置
- 1.打开配置文件: