读书-程序员的自我修养-链接、封装与库(22:第八章:Linux共享库的组织)

1. 共享库管理

1.1 为什么需要共享库管理?

因为动态链接的优点,导致程序中有大量的动态库或者叫做共享对象的存在。
如果没有进行管理,那么多的共享对象就可能存在各个目录下,给长期维护和升级带来不便。
故需要对共享对象进行管理包括目录存放,命名规则等。

1.2 共享库和共享对象关系

共享库(Shared Library),Linux共享库其实就是共享对象。
由于共享对象可以再程序之间共享,就导致其以库的形式存在了,所以开发者都是库以共享对象的形式存在。
故: 共享库和共享对象可以当做同一个东西。

1.3 共享库的兼容性

共享库的跟新分为两类:

  1. 兼容跟新:新增新内容,原接口不变
  2. 不兼容跟新:原接口改变

1.4 共享库命名方式

linux对共享库的命名规则如下: libNAME.x.y.z.so

  1. 以lib开头
  2. .so 结尾
  3. name 表示库的名字
  4. x 表示主版本号
    主版本号表示库的重大升级,因此不同主版本号之间库不兼容
  5. y 表示次版本号
    次版本号表示增量升级,因为不同次版本号之间库可兼容
  6. z 表示发布版本号
    发布版本号表示错误修正,性能优化等

1.5 SO-NAME

1.5.1 背景

从程序角度看,程序运行时怎么知道它需要哪些库?版本号又是什么?
SO-NAME 来解决这个问题。

1.5.2 定义

Linux 采用一种叫做 SO-NAME 的命名机制来记录各个共享库的依赖关系。
每个共享库,都有一个 SO-NAME。
它去除次版本号和发布版本号,如 libNAME.x.y.z.so 的SO-NAME 是 libNAME.x

1.5.3 作用

SO-NAME 通过软链接实现,它会指向主版本号相同,次版本号和发布版本号最新的共享库。

1.5.4 SO-NAME原则

SO-NAME表示一个库的接口,接口不向后兼容,SO-NAME就发生变化。这是基本原则。

1.5.5 ldconfig

linux中有个工具 ldconfig 它会遍历共享库,然后指向最新的共享库。

1.6 链接名

libNAME.x.y.z.so 的 NAME 就叫做链接名。
如链接的时候只要, -lNAME ,如 -lm 就是 libm.so 数学库

2. 符号版本

2.1 基于符号的版本机制

思想是:让每个导入和导出符号都有一个相关联的版本号。类似于符号修饰
例子:
如 libHELLO.1.1.1.so 的升级版本 libHELLO.1.2 libHELLO.1.3都保留 libHELLO.1.1 的SO-NAME,
但是给新版本(1.2 1.3等)中新增的那些符号打上标记 如 VER_1.3

3. 共享库系统路径

3.1 FHS

Filesystem Hierarchy Standard(文件系统层次化标准)
FHS 规定了系统中文件目录该如何存放,已经各个目录的结构,组织和作用等。

3.2 系统中存放共享库的位置

FHS 规定系统中两个存放共享库的位置。

  1. /lib 存放系统最关键和基础的共享库
    如 动态连接器 c语言运行库 数学库等

  2. /usr/lib 非系统运行时需要的关键共享库。
    主要是开发过程中用得到的共享库。

  3. /usr/local/lib 存放非操作所需的第三方软件用到的库
    如python相关的共享库

4. 共享库查找过程

4.1 ldconfig 作用

  1. 作用1是为各个共享库目录各个共享库创建,删除,跟新相应的SO-NAME(即相应的符号链接)。
  2. 作用2建立一个所有共享库的 SO-NAME 的缓存

5. 环境变量

5.1 LD_LIBRARY_PATH

  1. 环境变量 LD_LIBRARY_PATH 可以临时的改变共享库的查找路径,而不会影响系统运行。
  2. LD_LIBRARY_PATH 是由若干路径组成的环境变量,它们以冒号隔开。
  3. LD_LIBRARY_PATH 默认是空的
  4. 当我们设置了 LD_LIBRARY_PATH,那么进程在启动时,动态链接器在查找共享库时,首先去 LD_LIBRARY_PATH 中查找指定的目录
  5. 优点: 让我们方便的测试新的共享库和非标准的共享库

5.2 动态链接器查找动态库的顺序

有了 LD_LIBRARY_PATH 之后,动态链接器查找动态库的顺序为:

  1. 由环境变量 LD_LIBRARY_PATH 指定的路径
  2. 由路径缓存文件 /etc/ld.so.cache 指定的路径
  3. 默认共享路径 先 /usr/lib 再 /lib

6. 共享库的创建和安装

6.1 共享库的创建

-shared 表示结果是共享库类型的
-fPIC 使用地址无关代码技术

如: 创建动态链接库:
gcc -shared -fPIC -o libmyhello.so hello.o

6.2 共享库构造和析构函数

6.2.1 背景

很多时候,我们希望共享库在被装载时能够进行一些初始化工作,如文件打开,网络连接,使得共享库里面的接口能够正常运行。

6.2.2 attribute(constructor) 和 attribute(destructor)

GCC提供了共享库的构造函数,只要在函数声明前加上__attribute__(constructor)属性,就指定该函数为共享库的构造函数。
有这个属性的函数会在共享库加载时被执行,即在main之前被执行。
对于的析构函数就是 attribute(destructor)

7. 总结

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lqy971966/article/details/107644819