首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >一文带你了解Linux下共享库的版本管理

一文带你了解Linux下共享库的版本管理

作者头像
霞姐聊IT
发布2025-11-12 20:02:16
发布2025-11-12 20:02:16
2680
举报

大家在刚接触Linux开发时,看到系统里面安装的库,比如下面这样的,会不会有点迷惑?为什么库有多个版本?版本号还有长有短?实际运行时到底用了哪个库?

xlx@DESKTOP-OD8E9O2:/usr/lib/x86_64-linux-gnu$ ls libzstd*

libzstd.so.1 libzstd.so.1.5.5

今天,就让霞姐带你一起研究一下吧!

一、共享库为什么需要版本?

共享库发布后,随着时间的推移,开发者会发现原来的共享库会存在这样那样的不足,从而会对其进行更新。

但是为什么不直接替换原有的库,而是要在库名字之后加上“小尾巴”呢?

那是因为对原有共享库的更新,有些是兼容性更新,而有些是非兼容性更新。只是替代,而没有一套管理规则的话,会造成兼容性问题。

什么是兼容性更新呢?比如,修复原有逻辑里面的bug,或者增加了一个新的接口,或者改进了原有函数的性能,这类的更新不影响原来的接口的行为、调用方式,依赖这个共享库的其它程序不会受到影响。

什么是非兼容性更新呢?比如,删除了老共享库里面的一个接口,或者接口的参数发生变化,或者接口的行为和原来不一样了,这种更新会导致使用这个共享库的程序不能运行或者运行出问题。

那怎么样能保证共享库的更新不给其他程序造成混乱呢?Linux为了解决这个问题,使用了共享库版本控制技术。

二、版本命名约定

Linux系统上,一个典型的共享库的名字是这样的:libname.so.x.y.z。

共享库固定由lib开头,中间的name是库名,后缀so代表是共享库的意思,后面的数字,则是版本号。

1.X:Major主版本号

主版本号表示库的重大升级,只有在发布不兼容的库的时候才会改变。依赖于旧版本号的程序要改动相应的部分,重新编译,才能使用新版的共享库。

但也不需要共享库一升级,依赖它的原有程序也跟着升级。用户也可以选择保留旧的共享库以支持原有程序的正常运行。

2.Y:Minor次版本号

次版本号表示库的增量升级。即原有的不变,但新增了一些新的接口。高的次版本号兼容低的次版本号的库。

由于保留了原有的接口并且不改变它们的定义和含义,所以一个依赖旧的次版本号共享库的程序,换了新的次版本号共享库后,可以在运行时与新的库链接,正常工作。

反过来则不行。

3.Z:Release发布版本号

发布版本号表示库的一些错误的修正、性能的改进等,并不添加任何新的接口,也不对接口进行更改。主次版本号相同,发布版本号不同的共享库之间完全兼容,依赖它们的程序不需要做任何更改就可以正常工作。

可参考论文《Library Interface versioning in solaris and Linux》

查看细节,论文地址:

www.usenix.org/legacy/publications/library/proceedings/als00/2000papers/papers/full_papers/browndavid/browndavid_html/index.html#:~:text=This%20paper%20describes%20the%20library%20symbol-versioning%20technology%20in,to%20be%20applied%20in%20Linux%20versioned%20shared%20libraries.

三、可执行文件怎么知道自己依赖的共享库版本?

三类名字(realname、soname、linkname)互相配合,可以解决这个问题:

1.realname

realname是包含实际库代码的文件名,一般是就是上文介绍的包含三个版本号的libname.so.x.y.z。

比如下面这个例子中,libzstd.so.1.5.5就是这个库的realname。它是由gcc编译库代码生成的,而libzstd.so.1是一个指向它的软链接。

xlx@DESKTOP-OD8E9O2:/usr/lib/x86_64-linux-gnu$ ls -lh libzstd*

lrwxrwxrwx 1 root root 16 Aug 9 2024 libzstd.so.1 -> libzstd.so.1.5.5

-rw-r--r-- 1 root root 739K Aug 9 2024 libzstd.so.1.5.5

2.soname

soname通常是 realname 文件的软链接,一般叫做libname.so.x,只包含主版本号。

在库文件生成时,可以使用如gcc -shared -o (realname) (dependencies) (flags) -wl,-soname,(soname)的命令指定soname。

而编译程序时,程序会把它依赖的库的soname放进DT_NEED字段。

在程序运行时的加载阶段,动态链接器会根据用户程序编译时记录的soname 查找对应的共享库文件。

如果我们不使用soname,而是直接用realname的话,编译完的程序就和主、次、发布三个版本号绑定了。

如果这个时候依赖的库发生了升级,那么原来的库还得保存在系统上,否则程序aaa就没有办法运行。

根据上文我们对版本命名约定的说明可知,Minor次版本号表示库的增量升级,只是新增了一些新的接口的高的次版本号,会兼容低的次版本号的库。Release发布版本号之间更是完全兼容。

因此,使用了soname后,如果依赖库发生了Minor和Release级别的升级,可以把原来的库删除,把soname软链接直接定向到新的库,程序也可以运行。

如果依赖库发生了Major级别的升级,只需要新增一个soname的软链接,原有的soname不受影响,这样依赖原来的老库的程序不会受到影响。

所以,使用了soname,既可以获得扩展性,又保持兼容性,还能节约存储空间。

Linux的ldconfig可以自动维护soname和realname之间的关系:

3.linkname

linkname是没有任何版本编号的文件名libname.so,通常是realname 文件或soname 文件的软链接。

编译时,链接器使用-l中指定的库名,通过linkname来寻找对应的共享库,然后将共享库的 soname 记录在用户程序的动态链接信息中。

四、小结

libxxx.so.X.Y.Z 版本号三段式分别对应“主-次-发布”三级兼容性承诺,让开发者一眼就能判断这次升级是否安全。

realname 存代码,soname 定接口,linkname 管编译,ldconfig维护缓存和软链,既能让新程序享受新特性,又不对老程序造成混乱。

了解版本管理方法,把版本交给规则,把兼容留给系统,把创造力留给程序员!

前几天有读者给我私信,建议我写一篇共享库版本管理的文章,所以我梳理了相关材料输出了这篇文章。梳理的过程也是对我自己知识体系夯实的一个过程,所以其它的读者朋友,有建议也可以留言或者私信,我有空就可以安排起来,这样咱们都可以共同学习,共同成长。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 霞姐聊IT 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档