动态库的版本号命名规则
共享库的命名必须如 libname.so.x.y.z最前面使用前缀”lib”,中间是库的名字和后缀”.so”,最后三个数字是版本号。x是主版本号(Major Version Number),y是次版本号(Minor Version Number),z是发布版本号(Release Version Number)。
(1)主版本号(不兼容):重大升级,不同主版本的库之间的库是不兼容的。
(2)次版本号(向下兼容): 增量升级,增加一些新的接口但保留原有接口。高次版本号的库向后兼容低次版本号的库。
(3)发布版本号(相互兼容):库的一些诸如错误修改、性能改进等,不添加新接口,也不更改接口。主版本号和次版本号相同的前提下,不同发布版本之间完全兼容。
soname简介
soname用来记录共享库的依赖关系。每个共享库都有一个对应的“SO-NAME”(共享库文件名去掉次版本号和发布版本号)。soname在链接和加载库文件时,如果使用-lname链接库文件时,链接器会读取libname.so文件中的soname值,并将其记录在生成的程序中,当运行程序时,会从相应的目录加载名为soname的文件,所以,在运行程序之前,soname的库文件必须已生成。
soname的作用
soname的关键功能是它提供了兼容性的标准。在Linux中,应用程序通过使用soname,来指定所希望库的版本,库作者可以通过保留或改变soname来声明,哪些版本是兼容的,有利于库文件的升级和兼容。
soname的编译生成与查看
连接选项需要带上-Wl,-soname,soname(例如libsun.so.1)
例如:
gcc -fPIC -shared -o libsub.so.1.2 sub.c -Wl,-soname,libsun.so.1
sub.c生成一个名为libsub.so.1.2的共享库,且该共享库的soname为libhello.so.1。其中-Wl选项告诉编译器将后面的参数传递给链接器。-soname则指定了动态库的soname。
使用readelf -d $(realname)查看库文件的soname
root@chen:/home/chenjg/share/test/dynamic# readelf -d libsub.so.1.2
Dynamic section at offset 0xe38 contains 22 entries:
标记 类型 名称/值
0x0000000000000001 (NEEDED) 共享库:[libc.so.6]
0x000000000000000e (SONAME) Library soname: [libsun.so.1]
0x000000000000000c (INIT) 0x538
0x000000000000000d (FINI) 0x6a8
0x0000000000000019 (INIT_ARRAY) 0x200e20
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x200e28
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x1f0
0x0000000000000005 (STRTAB) 0x380
0x0000000000000006 (SYMTAB) 0x230
0x000000000000000a (STRSZ) 183 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x201000
0x0000000000000007 (RELA) 0x478
0x0000000000000008 (RELASZ) 192 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x458
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x438
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0
soname的生成
•采用软连接的方式生成该文件,如:ln -s $(realname) $(soname)
•使用ldconfig命令自动生成,如 ldconfig -n
(
d
i
r
)
会
生
成
(dir) 会生成
(dir)会生成(dir)目录下所有库文件对应的$(soname)文件。
sub.c的源文件
#include<stdio.h>
int sub(int a,int b)
{
return a-b;
}
int max(int a,int b)
{
return a>b?a:b;
}
总结:动态库是需要不断更新与维护,自然需要不同的版本号来区分。打的改动时,不同的版本是不兼容的,小的改动时,不同版本是兼容的,所以对于版本的兼容性管理就显得十分重要。在Linux中,需要用到soname来管理版本的兼容性问题。一个动态库一般都会有一个soname,默认情况视为libname.so,正常的管理方式,soname的模式一般为libname.so.x,如果动态库的版本号是兼容的,那么对于的soname就设置为相同,反之,设置为不同。