共享库soname机制

简介: 【7月更文挑战第4天】Linux共享库的soname机制管理版本,通过libname.so.x的形式区分主版本。soname(如libname.so.x)在程序编译时被记录,运行时动态链接器依据soname找对应的.so.x文件。linkname(libname.so)用于编译时链接。更新库时,soname不变则不影响已编译程序,新soname则需新旧版本共存。`ldconfig`用于更新系统共享库缓存。

共享库 soname(Short for Shared Object Name)机制是一种用于管理共享库版本的方法,它通过设计特定的命名方式来方便共享库的更新和使用,同时确保应用程序在运行时能够找到合适的库版本。


soname 机制涉及以下三种命名方式:


  1. realname:实际等同于库文件的文件名,一般格式为libname.so.x.y.z,其中lib是固定前缀,name是库名称,.so是共享库固定后缀,x代表主版本号,y表示次版本号,z则是发布版本号。拥有此名称的文件通常就是共享库的源文件。在库文件生成时,可以使用类似gcc -shared -o $(realname) $(dependencies) $(flags)的命令来指定 realname。
  2. soname:其一般格式为libname.so.x,其中x代表主版本号。它作用于用户程序运行时的加载阶段,动态链接器会根据用户程序编译时记录的 soname 查找对应的共享库文件。soname 通常是 realname 文件的软链接,在库安装或更新后,一般由库的维护者或系统管理员通过包管理器来更新软链接的指向,而不是由单个用户手动进行软链接。在库文件生成时,可以使用如gcc -shared -o $(realname) $(dependencies) $(flags) -wl,-soname,$(soname)的命令指定 soname。不同 realname 的库文件可以有相同的 soname,这有利于库文件的升级和兼容。例如,当版本从1.0.0升级到1.0.1,且库文件的接口没有变化(或者接口增加,但原有接口不变)的情况下,可以指定相同的 soname,这样使用1.0.0生成的程序仍然可以运行。
  3. linkname:其一般格式为libname.so,是没有任何版本编号的文件名。它作用于用户程序编译阶段,链接器使用 linkname 来寻找对应的共享库(在 gcc 中使用-l 选项指定库,如-laaa,链接器就会去找 libaaa.so),然后将共享库的 soname 记录在用户程序的动态链接信息中。linkname 通常是 realname 文件或 soname 文件的软链接,同样在库安装或更新后,一般由库的维护者或系统管理员通过包管理器更新软链接的指向,不由单个用户手动进行软链接。


总的来说,对于 Linux 下的用户程序,soname 命名机制主要参与了以下两个过程:


  1. 链接阶段:编译器按照搜索路径优先级,根据 linkname 去找对应的.so 文件,如果找到了就会在生成的可执行文件中记录.so 文件指向的共享库文件的 soname;如果没有找到就会去找静态库文件选择静态链接。
  2. 加载阶段:程序运行时,动态链接器按照搜索路径优先级,根据可执行文件中记录的 soname 去找对应的*.so.x 文件,如果找到了就会加载其指向的共享库;没找到就报错。


这样的处理确保了应用程序在运行时能够找到合适的库版本,同时允许系统管理员在不影响已有应用程序的情况下更新库文件。例如,当共享库进行小版本升级(接口不变)时,soname 保持不变,只需更新 soname 的软链接指向新版本的 realname 即可,应用程序能自动使用新版本的共享库;而当进行主版本升级(接口发生变化)时,soname 会加 1,此时新旧版本的共享库需同时存在,新程序使用新 soname,旧程序仍使用旧 soname。


此外,Linux 系统通常提供了ldconfig命令来自动生成或更新 soname 文件,以加速共享库的加载,并将系统的共享库信息放到一个缓存文件(/etc/ld.so.cache)中,提高查找速度。但需注意,在修改了/etc/ld.so.conf 文件或者在系统中安装了新的函数库之后,需要运行ldconfig命令来刷新系统的共享库缓存。

相关文章
|
4月前
|
存储 Linux 编译器
【Linux】详解动态库链接和加载&&对可执行程序底层的理解
【Linux】详解动态库链接和加载&&对可执行程序底层的理解
137 1
|
4月前
|
算法 网络协议 Linux
Linux模块文件编译到内核与独立编译成.ko文件的方法
Linux模块文件编译到内核与独立编译成.ko文件的方法
1121 0
|
11月前
|
机器学习/深度学习 运维 自然语言处理
系统程序的编译与处理
系统程序的编译与处理
将模块编译入内核
将模块编译入内核
100 0
|
Linux 编译器 Shell
【Linux系统编程】静态库和共享库
【Linux系统编程】静态库和共享库
141 0
|
Linux
Linux环境显式使用动态库
Linux环境显式使用动态库
128 0
玩转Makefile | 编译有共用文件的多个程序
玩转Makefile | 编译有共用文件的多个程序
277 0
玩转Makefile | 编译有共用文件的多个程序
|
Java
静态链接,静态分派,动态链接
静态链接,静态分派,动态链接
148 0
|
存储 SQL 移动开发
我的数据访问函数库的源代码(一)—— 共用部分
/* 2008 4 25 更新 */ 我的数据访问函数库的源码。整个类有1400多行,原先就是分开来写的,现在更新后还是分开来发一下吧。 第一部分:内部成员,初始化设置等。    1using System;  2using System.
814 0