共享库的版本控制
2022/8/2 23:23:04
本文主要是介绍共享库的版本控制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
共享库的版本控制
关于 SONAME
编译动态库时,可以指定 SONAME 。程序运行时,加载器(Dynamic Loader)发现动态库有 DT_SONAME 字段,则会转而去链接 DT_SONAME 指定的动态库。
应用:库的版本
Linux 动态库的版本号一般格式为 lib + libname + .so + 主版本号 + 子版本号 + 发行版本号 。
情况一:如果版本号发生了改变之后,实际库仍然是兼容的,此时更新软链接,将主版本,即可实现库的更新。
情况二:如果版本号发生了改变之后(一般是主版本),库不再兼容,此时变更 SONAME ,即可实现库的多版本兼容(多个库同时存在,由程序根据 SONAME 选择加载)。
例子:
// add.c // V1.0.0 int add(int a, int b) { return a+b; }
// main.c #include<stdio.h> int add(int a, int b); int main() { int a = 1; int b = 2; int c = add(a, b); printf ("c=%d\n", c); return 0; }
对第一种情况:
版本更新前:
gcc add.c -shared -fPIC -Wl,-soname=libadd.so.1 -o libadd.so.1.0.0 ldconfig -nv . ln -s libadd.so.1 libadd.so gcc main.c -L. -ladd export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./a.out
观察动态库和 a.out 的符号:
readelf -d libadd.so.1.0.0 Dynamic section at offset 0x2e80 contains 18 entries: Tag Type Name/Value 0x000000000000000e (SONAME) Library soname: [libadd.so.1] readelf -d a.out Dynamic section at offset 0x2db0 contains 28 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libadd.so.1]
也即,编译库的时候,生成的库的名字为最完整的名字(比如 libadd.so.1.0.0),库的 SONAME 字段为兼容版本的库名字(比如 libadd.so.1)。生成 a.out 时,链接的名字始终使用 -ladd ,也即需要创建一个 libadd.so 的链接指向兼容版本的库。最终生成 a.out 时,依赖的库的名字是根据 libadd.so 中的 SONAME 字段生成的(SONAME 字段存在时),也即 a.out 依赖的库名字为 libadd.so.1。
注意:libadd.so 只有编译生成 a.out 时需要使用(DEV)。如果只是部署,则只需要 libadd.so.1 和 libadd.so.1.0.0 就行了。
版本更新后(更新后仍然兼容,只更新子版本号):
rm libadd.1.* gcc add.c -shared -fPIC -Wl,-soname=libadd.so.1 -o libadd.so.1.1.0 ldconfig -nv .
版本更新时,先删除当前已有的兼容版本,然后生成新的兼容版本,并利用 ldconfig 更新兼容版本链接。
ldconfig -nv . .: libadd.so.1 -> libadd.so.1.1.0 (changed)
兼容版本更新过程中,需要删除已有版本。
对第二种情况:
// add.c // V1.0.0 int add(int a, int b, int c) { return a+b+c; }
// main.c #include<stdio.h> int add(int a, int b, int c); int main() { int a = 1; int b = 2; int c = add(a, b, b); printf ("c=%d\n", c); return 0; }
如果出现了库的不兼容版本更新,则两个库可以兼容存在。旧的程序链接旧版本的库,新的程序链接新版本的库,彼此互不干扰。
gcc add.c -shared -fPIC -Wl,-soname=libadd.so.2 -o libadd.so.2.0.0 ldconfig -nv . ln -s libadd.so.2 libadd2.so gcc main.c -L. -ladd2 -o a2.out export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./a2.out
这里我们把用于编译的库的名字做了区分(libadd.so 和 libadd2.so),这时为了编译的时候进行版本区分。
这样就实现了多个库的兼容。
这篇关于共享库的版本控制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行