链接库(动态链接库,静态链接库)

508 阅读3分钟

阅读并整理了一些网上的资料,做个记录

库最基本的概述:是共享代码的方法

链接库是什么

库: 专门存储可重复使用代码块的文件

但是一般不会直接分享源代码,而是分享库的二进制版本——链接库


一个目标文件中使用的函数或变量,可能定义在其他的目标文件中,也可能定义在某个链接库文件中。链接器完成完成链接工作的方式有两种,分别是:

  • 无论缺失的地址位于其它目标文件还是链接库,链接库都会逐个找到 各目标文件中缺失的地址。采用此链接方式生成的可执行文件,可以 独立载入内存运行
  • 链接器先从所有目标文件中找到部分缺失的地址,然后将所有目标文件组织成一个可执行文件。如此生成的可执行文件,仍缺失部分函数和变量的地址,待文件执行时,需连同所有的链接库文件一起载入内存,再由链接器完成剩余的地址修复工作,才能正常执行。

第一种链接方式为静态链接;第二种,链接所有目标文件也为静态链接,但是在内存中链接属于动态链接

静态链接库

有很多缺点:

  1. 文件体积很大
  2. 如果存在多个可执行文件,都链接同一个静态库,那么每个可执行文件都要全量链接该静态库,造成资源浪费
  1. 一旦程序中有模块更新,那么都要重新链接才能运行

动态链接库

在Linux上习惯称为 共享库、共享对象文件

动态链接:将链接的时机推迟到程序运行时再进行

  1. 动态链接库可执行文件分别载入内存的
  2. 多个程序同一个动态链接库时,所有程序可共享一份动态链接库,避免空间浪费
  1. 方便了程序的更新,如果程序有一个模块更新,那么只需要替换旧的模块,然后动态链接在一起

但是,每次程序运行都需重新链接,比静态链接库相比损失了大概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。被加载器加载到内存中运行,然后动态链接器执行重定位代码和数据的工作

具体的执行过程:

  1. 重定位libc.so(C语言函数库) 到一个位置
  2. 重定位libvector.so到另一个位置
  1. 重定位prog2中的那些定义于libc.so libvector.so的引用符号

如何使用(动态)共享库

  • dlopen可以打开一个共享库文件,RTLD_LAZY代表,当共享库中函数执行时再进行符号解析
  • dlsym:handle是共享库文件的句柄,symbol是符号名。返回符号的地址
  • dlclose:卸载共享库