內核長篇分享

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 等。