一、共享库版本
问题来源:共享库会不停更新版本、修复BUG以及增加新的功能等。而应用程序本身独立于共享库开发。所以管理共享库兼容性至关重要。
导致C语言共享库ABI改变的行为主要有以下4种:(1)库函数(导出函数)被删除;(2)导出数据的结构发生变化;(3)导出函数的接口变化;(4)导出函数行为发生变化。
共享库版本命名:
libname.so.x.y.z
name 库的名字;
x 主版本号 表示重大升级,不同主版本号的库之间不兼容;
y 次版本号 库的增量升级,即增加一些新接口符号,且保持原来的符号不变。在主版本号不变的情况下,高的次版本号的库向后兼容低次版本号库。
z 发布版本号 库的一些错误的修正、性能的改进等,并不添加任何新的接口,也不对接口进行更改。相同主版本号、次版本号的共享库,不同的发布版本号之间完全兼容。
SO-NAME:
每个共享库都有一个对应的SO-NAME,这个SO-NAME即共享库的文件名去掉次版本号和发布版本号,保留主版本号。例如,共享库libfoo.so.2.6.1的SO-NAME是libfoo.so.2 。 在Linux系统中系统会为每个共享库在它所在的目录创建一个跟SO-NAME相同的并且指向它的软链接(Symbol Link)。
SO-NAME永远指向相同主版本号中次版本号和发布版本号最新的共享库,保证了兼容性。
当共享库实现增量升级(y修改),只需改变软连接指向最新版本共享库即可;而重大升级(x修改)时,则需要创建新的SO-NAME,同时保留旧的SO-NAME。
二、共享库系统路径和查找顺序
Linux遵守FHS (File Hierarchy Standard)的标准,这个标准规定了一个系统中的系统文件应如何存放。FHS规定,一个系统中主要有3个存放共享库的位置:
/lib 系统最关键和基础的共享库(如动态链接器、C语言运行库、数学库等);
/usr/lib 非系统运行时所需要的关键性的共享库,主要是开发时用到的共享库(用户程序或shell一般不用);
/usr/local/lib 主要是第三方应用程序的库,如python解释器对应的库/usr/local/lib/python。
查找顺序:
1. 如果DT_NEED里面保存的是绝对路径,那么动态链接器就按照这个路径去查找;
2. 如果DT_NEED里面保存的是相对路径,则按照下面的顺序查找:
(1) 由环境变量LD_LIBRARY_PATH指定的路径
(2)由路径缓存文件/etc/ld.so.cache指定的路径
(3)默认共享目录/usr/lib
(4)默认共享目录/lib
环境变量:
LD_LIBRARY_PATH 可以临时改变应用程序的共享库查找路径,而不会影响系统中的其他程序;
LD_PRELOAD 预先装载的共享库,优先于指定目录中的共享库;
LD_DEBUG 打开动态链接器的调试功能,动态链接器在运行时打印出各种有用信息。