共享库 soname(Short for Shared Object Name)机制是一种用于管理共享库版本的方法,它通过设计特定的命名方式来方便共享库的更新和使用,同时确保应用程序在运行时能够找到合适的库版本。
soname 机制涉及以下三种命名方式:
- realname:实际等同于库文件的文件名,一般格式为
libname.so.x.y.z
,其中lib
是固定前缀,name
是库名称,.so
是共享库固定后缀,x
代表主版本号,y
表示次版本号,z
则是发布版本号。拥有此名称的文件通常就是共享库的源文件。在库文件生成时,可以使用类似gcc -shared -o $(realname) $(dependencies) $(flags)
的命令来指定 realname。 - 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生成的程序仍然可以运行。 - linkname:其一般格式为
libname.so
,是没有任何版本编号的文件名。它作用于用户程序编译阶段,链接器使用 linkname 来寻找对应的共享库(在 gcc 中使用-l 选项指定库,如-laaa,链接器就会去找 libaaa.so),然后将共享库的 soname 记录在用户程序的动态链接信息中。linkname 通常是 realname 文件或 soname 文件的软链接,同样在库安装或更新后,一般由库的维护者或系统管理员通过包管理器更新软链接的指向,不由单个用户手动进行软链接。
总的来说,对于 Linux 下的用户程序,soname 命名机制主要参与了以下两个过程:
- 链接阶段:编译器按照搜索路径优先级,根据 linkname 去找对应的.so 文件,如果找到了就会在生成的可执行文件中记录.so 文件指向的共享库文件的 soname;如果没有找到就会去找静态库文件选择静态链接。
- 加载阶段:程序运行时,动态链接器按照搜索路径优先级,根据可执行文件中记录的 soname 去找对应的*.so.x 文件,如果找到了就会加载其指向的共享库;没找到就报错。
这样的处理确保了应用程序在运行时能够找到合适的库版本,同时允许系统管理员在不影响已有应用程序的情况下更新库文件。例如,当共享库进行小版本升级(接口不变)时,soname 保持不变,只需更新 soname 的软链接指向新版本的 realname 即可,应用程序能自动使用新版本的共享库;而当进行主版本升级(接口发生变化)时,soname 会加 1,此时新旧版本的共享库需同时存在,新程序使用新 soname,旧程序仍使用旧 soname。
此外,Linux 系统通常提供了ldconfig
命令来自动生成或更新 soname 文件,以加速共享库的加载,并将系统的共享库信息放到一个缓存文件(/etc/ld.so.cache)中,提高查找速度。但需注意,在修改了/etc/ld.so.conf 文件或者在系统中安装了新的函数库之后,需要运行ldconfig
命令来刷新系统的共享库缓存。