内核长篇分享

Linux 共享库的 soname 命名机制

引言

做 Pwn 题时,经常会需要切换 libc,总会看见诸如 libc.so.6 的名称,一直不理解它背后的含义,今天学习了 Linux 下共享库的组织才恍然大悟。

在说 libc.so.6 之前,需要先了解共享库版本号的概念so-name 命名机制

共享库版本号

版本号类型

共享库一般会不断更新以修复 bug、更改接口。有些更新是向后兼容的;有些更新是不兼容的,会导致依赖该库的程序无法运行或需要重新编译才能运行。

根据这些更新的兼容性,划分为不同的版号:主版本号(Major Version Number)次版本号(Minor Version Number)发布版本号(Release Version Number)

主版本号表示库的重大升级。不同主版本号的库之间互不兼容,需要更改接口,并重新编译。依赖于旧共享库的程序可能需要在系统中保留一份旧版的共享库才能运行。

次版本号表示库的增量升级,即增加一些新的接口符号,并保持原有符号不变。依赖于低次版本号共享库的程序可以在高次版本号的共享库下正常运行。

发布版本号表示库的一些错误的修正、性能的改进等,接口不做变化。不同发布版本号之间完全兼容。

共享库文件命名规则

Linux 有一套规则来命名系统中的每一个共享库,它规定共享库的文件命名规则如下:

libname.so.x.y.z

前缀"lib"+库名称+后缀".so"+三个数字组成的版本号,其中,x 表示主版本号y 表示次版本号z 表示发布版本号

例如,libfoo.so.2.6.1 表示的就是版本号为 2.6.1 的共享库 foo。

但也存在一些不遵守这套命名规定的,比如最基本的 C 语言库 Glibc 使用 libc-x.y.z.so 这种命名方式。

SO-NAME 命名机制

新的操作系统,包括 Solaris 和 Linux,普遍采用一种叫做 SO-NAME 的命名机制,就是把共享库的文件名去掉次版本号和发布版本号,只保留主版本号

例如,一个共享库叫 libfoo.so.2.6.1,那么它的 SO-NAME 就是 libfoo.so.2。

在 Linux 系统中,系统会为每个共享库在它所在的目录创建一个跟它的 ”SO-NAME” 一样的软链接指向它。当共享库更新时,这个软链接会始终指向主版本号相同、次版本号和发布版本号最新的那个库文件。

例如,目录中同时有 /lib/libfoo.so.2.6.1 和 /lib/libfoo.so.2.5.3 的两个不同版本的共享库,软链接 /lib/libfoo.so.2 就会指向 /lib/libfoo.so.2.6.1 的那个共享库。

依赖于某个共享库的文件只需要保存这个共享库的 SO-NAME,就可以保证始终在使用系统中最新的主版本号的共享库了,而无需在系统中保存各种版本的共享库。

总结

说回 libc.so.6,我们知道现在我们使用的 libc 是 GNU 的 libc,也叫 glibcglibc 目前版本是 2.x,按之前说的 SO-NAME 机制,应该是 libc.so.2 才对,但实际上却是 libc.so.6。

这是因为,早期 Linux 内核开发者们 fork 了一份 glibc,独立维护了第 2 版到第 5 版的 Linux libc(第 1 版的 libc 还是是 glibc)。但因为版权归属的问题,没有合并回去。后来 glibc 2.0 发布了,把 POSIX 标准实现得很好,他们就又用回 glibc 了。继此之后,glibc 自己的版本号虽然是 2.x,但由于最后使用的 Linux libc 的 soname 已经叫 libc.so.5 了,它就只能从 .6 开始计数了。

参考

  1. 《程序员的自我修养》第8章
  2. glibc - 维基百科, https://en.wikipedia.org/wiki/Glibc

本文链接: https://linuxstory.org/soname-of-linux-shared-library

LinuxStory 原创文章,转载请注明出处,否则必究相关责任。

对这篇文章感觉如何?

太棒了
0
不错
0
爱死了
1
不太好
0
感觉很糟
0

You may also like

Leave a reply

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

More in:内核

内核

rootfs initramfs kexec 与 Linux 启动过程

作为 Debian 用户,在使用 apt 更新系统时偶尔会发现某次安装更新的时间特别长,这往往出现在较大版本的更新中,仔细观察后就会发现,这个耗时极长的操作并不是安装某个软件,而是对一个名为 init […]
内核

龙芯开始发布针对3A6000系列CPU的Linux补丁

尽管龙芯3A6000处理器尚未正式推出,但自去年以来的传言将其定于在今年上半年推出,并有人声称这种性能提升可以与AMD Zen 3或英特尔Tiger Lake的性能水平相媲美。在3A6000系列推出之 […]
内核

Linux 5.6 内核发布

Linux 5.6 kernel 正式发布。显著的新特性包含 WireGuard 进入主线、对 USB4 的初步支持、Time Namespace 等。