【程序员的自我修养】8. Linux共享库的组织

共享库版本

共享库兼容性

 更新方式:

  • 兼容更新:在原有的基础上添加内容,原有接口保持不变
  • 不兼容更新:原有接口改变,使用该共享库原有的接口程序可能不能允许或运行不正常

ABI接口(二进制接口):包含函数的堆栈接口、符号命名、参数规则和数据结构的内存分布

导致C语言共享库ABI改变的行为包括:

  • 函数的产生的结果和之前不一样
  • 函数被删除
  • 数据结构发生变化,如结构成员的删除、顺序改变等
  • 函数接口发生改变,如函数参数和返回值改变

对于C++的ABI来说,不同的编译器对C++特性的支持方案不同且互不兼容,要注意以下几点:

  • 不在接口类中使用虚函数,不随意增删改虚函数,因为会导致虚函数结构表发生变化
  • 不要改变类中任何成员变量的位置和类型
  • 不要删除非内嵌的public或protected成员函数
  • 不要改变成员函数的访问权限
  • 不要在接口中使用模板
  • 干脆不要使用C++作为共享库接口

共享库版本命名

共享库版本的命名规则:libname.so.x.y.z

  • 前缀lib
  • name:库的名字
  • .so:共享库的标识
  • x:主版本号
    • 表示库的重大升级
    • 不同主版本号的库之间不兼容
  • y:次版本号
    • 表示库的增量升级,即增加新的接口符号,且保持原来的符号不变
    • 在主版本号相同的情况下,高的次版本号向下兼容
  • z:发布版本号
    • 表示错误的的修正、性能的改进等,不增加任何新的接口,也不对接口更改
    • 相同的主版本号和次版本号,不同的发布版本号之间完全兼容

Glibc不适用这种规则,部分库的命名规则如下

  • C语言库:libc-x.y-z.so
  • 动态链接库:ld-x.y.z.so

SO-NAME

一种命名机制:

  • 共享库版本名称保留主版本号,去掉次版本号和发布版本号
  • 在共享库目录下创建软连接,指向主版本号相同,次版本号和发布版本号最新的共享库
$ ls -l /usr/lib32/libstdc++*
lrwxrwxrwx 1 root root      19 Jul  9  2023 /usr/lib32/libstdc++.so.6 -> libstdc++.so.6.0.28
-rw-r--r-- 1 root root 1906424 Jul  9  2023 /usr/lib32/libstdc++.so.6.0.28

作用:

  • 在编译的时候,所有依赖共享库的模块,都是用SO-NAME,不使用具体版本号
  • 如果使用具体版本,系统将保留大量的各个版本的共享库,浪费磁盘和内存空间
$ readelf -d /usr/lib32/libc.so.6 
Dynamic section at offset 0x1e7d6c contains 26 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [ld-linux.so.2]
  • 当版本库升级的时候,如果只做增量升级,直接修改软连接指向最新的版本即可升级
  • 如果是主版本号升级,系统中会保存多个SO-NAME,已有程序不影响

系统中有一个工具:ldconfig

  • 当更新共享库时,该工具会遍历所有默认共享库的目录,更新软连接,指向最新版本库
  • 如果是安装一个新的共享库,该工具会创建相应的软连接

链接名:在编译时候使用需要链接到某个库,如libXXX.so.2.6.1,XXX称为链接名

  • 只需要在命令行指定 gcc -lXXX,编译器会在-L指定目录搜索最新版本的XXX库
  • 并且根据参数指定不同版本(指定参数 -lc)
    • -static,系统会查找静态版本库,如 libc.a
    • -Bdynamic,系统会查找最新动态版本库,如 libc.so.x.y.z

你可能感兴趣的:(linux,运维,服务器)