静态库和动态库
1.库的概念
1.1 库是什么?
库是通过gcc编译得到的
本质:还是一个文件,这个文件里面就是程序员编写的经过编译,汇编后的功能代码。
1.2 为什么要使用库
为了代码保密,以及分发和部署。
1.3 库有了如何使用
要有动态库/静态库文件
要有头文件,头文件里面定义了动态库/静态库文件实现的功能。
然后我们可以根据头文件API在我们自己的程序中使用库函数。
2 静态库
2.1.命名规则
Linux上静态库的命名规则:
libxxx.so
lib 前缀,固定
xxx 库的名字,自己定义
.a 后缀,固定
Windows静态库命名规则
libxxx.lib 详解同上
2.2 如何制作库文件?
静态库的制作:
首先我们要有想要制作成库文件的.c/.cpp的源文件;
然后把他们进行预处理(-E),编译(-S),链接(-c),生成了.o为后缀的二进制文件。
接下来使用ar -rcs libxxx.a xx.o格式的命令进行静态库文件的制作
最后进行静态库文件中功能函数的调用:
我们编译链接main.c文件的时候需要指定-I(大i,键盘打不出来)寻找include头文件的路径(里面有库文件的.h文件),
-L 指定库文件所在的路径,-l指定库文件名(去掉lib和.a)。
3.动态库
3.1 命名规则:
linux:
libxxx.so
lib -> 前缀, 固定
xxx -> 库的名字, 随便起名
.so -> 后缀, 固定
在linux下是一个可执行文件
windows:
非vs制作
libxxx.dll
如果是使用vs制作的:
libxxx.lib
libxxx.dll
3.2 如何制作动态库
1. 使用gcc 得到 .o, 得到和位置无关的代码
gcc sub.c add.c div.c mult.c -c -fpic
-fpic/-fPIC: 使用相对地址记录代码的位置
产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
2. 使用gcc 得到动态库
gcc -shared xxx.o -o libxxx.so
3.动态库使用
首先分发: 头文件, 动态库,给需要使用动态库中函数所提供的功能的人。
然后编写测试文件,运行
gcc main.c -o app -I ./include/ -L ./ -lcalc
- 这是只是保证在连接的时候没问题
动态库会提示加载失败,找不到动态库文件,运行的时候需要给系统设置动态库的加载路径
可以通过ldd 可执行文件查看系统能不能找到当前可执行文件的动态库文件,我已经配置了路径所以能找到。
在执行的时候是如何定位共享库文件的呢?
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系
统的动态载入器(dynamic linker/loader)来获取该绝对路径。
对于elf格式的可执行程序,是由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ---> 环境变量
LD_LIBRARY_PATH ---> /etc/ld.so.cache文件列表 ---> /lib/,/usr/lib目录 找到库文件后将其载入内存。
第一种设置方法: 将动态库的绝对路径添加到 LD_LIBRARY_PATH 中
1. 测试时候使用的, 终端关闭, 设置失效:
在当前终端中执行: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库绝对路径
2. 长久设置, 将export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库绝对路径写到配置文件中
- 用户级别: ~/.bashrc
添加: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库绝对路径
- 系统级别: /etc/profile
添加:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库绝对路径
添加完成执行命令, 使修改生效:
. ~/.bashrc -> . 相当于 source
. /etc/profile
source /etc/profile
第二种: 在 /etc/ld.so.cache 中添加动态库路径
需要间接完成这个操作:
1. 找一个文件: /etc/ld.so.conf,配置动态库的路径
2. 进行更新: ldconfig
4. 动态库与静态库对比:
静态库:
优点:
静态库被打包到应用程序中加载速度快
发布程序无须提供静态库,移植方便
缺点:
消耗系统资源,浪费内存
更新,部署,发布麻烦
动态库:
优点:
可实现进程间资源共享
程序升级简单
程序员可以控制何时加载动态库
缺点:
加载速度比静态库慢
发布程序需要提供依赖的动态库