阅读并整理了一些网上的资料,做个记录
库最基本的概述:是共享代码的方法
链接库是什么
库: 专门存储可重复使用的代码块的文件
但是一般不会直接分享源代码,而是分享库的二进制版本——链接库
一个目标文件中使用的函数或变量,可能定义在其他的目标文件中,也可能定义在某个链接库文件中。链接器完成完成链接工作的方式有两种,分别是:
- 无论缺失的地址位于其它目标文件还是链接库,链接库都会逐个找到 各目标文件中缺失的地址。采用此链接方式生成的可执行文件,可以 独立载入内存运行;
- 链接器先从所有目标文件中找到部分缺失的地址,然后将所有目标文件组织成一个可执行文件。如此生成的可执行文件,仍缺失部分函数和变量的地址,待文件执行时,需连同所有的链接库文件一起载入内存,再由链接器完成剩余的地址修复工作,才能正常执行。
第一种链接方式为静态链接;第二种,链接所有目标文件也为静态链接,但是在内存中链接属于动态链接
静态链接库
有很多缺点:
- 文件体积很大
- 如果存在多个可执行文件,都链接同一个静态库,那么每个可执行文件都要全量链接该静态库,造成资源浪费
- 一旦程序中有模块更新,那么都要重新链接才能运行
动态链接库
在Linux上习惯称为 共享库、共享对象文件
动态链接:将链接的时机推迟到程序运行时再进行
- 动态链接库和可执行文件是分别载入内存的
- 多个程序用同一个动态链接库时,所有程序可共享一份动态链接库,避免空间浪费
- 方便了程序的更新,如果程序有一个模块更新,那么只需要替换旧的模块,然后动态链接在一起
但是,每次程序运行都需重新链接,比静态链接库相比损失了大概5%的性能
后缀:linux中为 .so,windows中为 .dll
gcc -shared -fpic -o libvector.so addvec.c mulvec.c
gcc -o prog2 main.c ./libvector.so // 通过共享库构建可执行文件
-shared: 指定创建共享库
-fpic: 共享库可以加载到内存任意位置
libvector.so的代码没有真的被复制到 prog2中,而静态库就会。
执行过程中,加载器会发现prog2中存在一个 名为.interp的section,其包含了动态链接器的路径名
实际上,动态链接器也是一个so文件,ld-linux.so。被加载器加载到内存中运行,然后动态链接器执行重定位代码和数据的工作
具体的执行过程:
- 重定位libc.so(C语言函数库) 到一个位置
- 重定位libvector.so到另一个位置
- 重定位prog2中的那些定义于libc.so libvector.so的引用符号
如何使用(动态)共享库
- dlopen可以打开一个共享库文件,RTLD_LAZY代表,当共享库中函数执行时再进行符号解析
- dlsym:handle是共享库文件的句柄,symbol是符号名。返回符号的地址
- dlclose:卸载共享库