这篇文章给大家介绍unix平台动态连接库的管理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
世界上唯一不变的是变化,对于动态连接库更是如此。动态库天生为方便程序的更新而设计,只需要替代库文件,无需重新编译主程序,即可运行更新后的版本。另外,动态库是多应用共享的,多个程序使用同一个库,那么库只会加载一份。
但是,现实往往不这么简单。既然动态库有新版本,那就会有与旧版本兼容或者不兼容的情况出现。当系统里存在多个使用此动态库的应用程序时,如果是兼容旧版本的更新还好,如果是不兼容,那么使用旧版本的应用程序就会受影响不能正常运行。特别的,当动态库集中放在系统指定的库目录下时(windows的system32),版本的冲突就形成了著名的“windows dll hell”。
为了解决这个问题,很多UNIX系统使用了ELF格式的DT_SONAME字段来应对。例如,linux的ld命令中,就有这么一个选项。
-h name
-soname=name
When creating an ELF shared object, set the internal DT_SONAME
field to the specified name. When an executable is linked with a
shared object which has a DT_SONAME field, then when the executable
is run the dynamic linker will attempt to load the shared object
specified by the DT_SONAME field rather than the using the file
name given to the linker.
表示使用-h或者-soname选项,可以在动态库里指定DT_SONAME字段,保存运行时查找的动态库名字,使得编译时和运行时动态库名可以不同。例如,编译libwel.so时使用-soname=libwel.so.1,那么编译可执行程序时-lwel,连接libwel.so,会记录运行时在搜索路径查找libwel.so.1加载。
ELF是一种应用非常广泛的二进制目标格式,与之类似的,UNIX的二进制目标还有a.out格式(SCO UNIX),XCOFF格式(AIX)。这两种格式就无法支持soname了。
那么,如何使多个版本的动态连接库同时支持呢,总结一下使用这种命名方式既可以新旧不兼容版本共存,又可以兼容版本正常升级。动态库命名为libxxx.so.n.m,soname名为libxxx.so.n,建立软连接libxxx.so指向最新的n版本libxxx.so.n供编译可执行程序使用,建立软连接libxxx.so.n指向版本n最新的m版本。这样,n的变化表示不兼容旧版本的改动,相同n下m的变化表示兼容n版本的改动。
还是以libwel.so举例。1.0版本的wel.c提供的函数void welcome(void) { printf("aaa\n"); },编译成库libwel.so.1.0,soname为libwel.so.1。建立软连接libwel.so.1,libwel.so。使用1.0库的主程序main1.c调用welcome(),编译成main1程序。1.1版本的wel.c改成void welcome(void) { printf("bbb\n"); },动态库只修改内部实现,对外接口兼容1.0版本,编译成库libwel.so.1.1。此时更新软连接libwel.so.1为libwel.so.1.1,主程序main1无需变动,即可输出更新后的bbb。2.0版本的wel.c改变了对外接口,提供的函数void welcome(char *p) { printf("%s\n",p); }。编译成库libwel.so.2.0,soname为libwel.so.2。建立软连接libwel.so.2,libwel.so。使用2.0库的主程序main2.c应以一个参数调用welcome("test")。main1和main2主程序互不兼容,必须分别调用版本1和版本2的库。此时,库目录下存在libwel.so.1指向1.1版本,libwel.so.2指向2.0版本,main1会连接1.1版本运行,main2会连接2.0版本运行。由此可见,小版本升级时应用程序自动使用最新版本,大版本升级时,使用旧版本的“过时”应用程序不受影响,从而避免了动态库版本的混乱。
同样,以link方式为例,给出各UNIX平台加设soname的动态库编译方法。(AIX不支持)
linux:
编译libwel.so:
gcc -fPIC -shared -Wl,-soname,libwel.so.1 -o libwel.so.1.0 wel.c -lc
ln -sf libwel.so.1.0 libwel.so.1
ln -sf libwel.so.1 libwel.so
-Wl,-soname,libwel.so.1 指定libwel.so.1.0的实际soname为libwel.so.1
sco unix open server:
编译libwel.so:
cc -K pic -G -h libwel.so.1 -o libwel.so.1.0 wel.c -lc
ln -sf libwel.so.1.0 libwel.so.1
ln -sf libwel.so.1 libwel.so
-h libwel.so.1 指定libwel.so.1.0的实际soname为libwel.so.1
HP UX:
编译libwel.so:
cc +z -c wel.c
ld -b -o libwel.sl.1.0 wel.o +h libwel.sl.1 -lc
ln -sf libwel.sl.1.0 libwel.sl.1
ln -sf libwel.sl.1 libwel.sl
+h libwel.sl.1 指定libwel.sl.1.0的实际soname为libwel.sl.1
SUN OS:
编译libwel.so:
cc -G -h libwel.so.1 -o libwel.so.1.0 wel.c -lc
ln -sf libwel.so.1.0 libwel.so.1
ln -sf libwel.so.1 libwel.so
-h libwel.so.1 指定libwel.so.1.0的实际soname为libwel.so.1
关于unix平台动态连接库的管理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。