- 前言
- 共享庫版本號
- 共享庫命名機制
- realname
- soname
- linkname
- 總結
- 參考文章
前言
在使用第三方庫時,我們會發現第三方庫會提供一組檔案,他們的字尾一般是.so
(如libname.so
),.so.x
和.so.x.y.z
。本文討論他們之間的關係。
共享庫版本號
共享庫一般會由於修復bug或增加介面等原因不斷更新,有些更新是向下相容的,有些則不是。一旦不向下相容,那麼當共享庫更新後,依賴該庫(舊版本)的程式將無法執行,需要重新編譯。
為了避免上述情況,就要對共享庫進行版本控制。根據更新內容的不同可以劃分不同的版本號:
- 主版本號(Major Version Number):主版本號表示庫的重大升級,即更新的內容會導致不再與舊版本相容(如介面變更),需要使用者做出程式碼上的修改來適應新版本(或者仍使用舊版的共享庫)。
- 次版本號(Minor Version Number):次版本號表示庫的增量升級,即更新的內容向下相容,不會影響使用者程式,但提供了額外的功能或改進。使用者不需要做出程式碼更改仍可繼續使用該庫。
- 釋出版本號(Release Version Number):釋出版本號表示庫的一些錯誤的修正、效能的改進等,介面不做變化,不新增新功能。向下相容。
不同的版本號在檔案命名上就可以體現。
對於一個名為aaa
的庫,它的共享庫檔名可能為:libaaa.so.x.y.z
,其中:
lib
:固定字首aaa
:庫名稱.so
:共享庫固定字尾.x
:主版本號.y
:次版本號.z
:釋出版本號
例如libjsoncpp.so.1.7.4
就代表著jsoncpp
的共享庫檔案,版本號為1.7.4
共享庫命名機制
然而若一個共享庫改變了版本號並更新檔案。那麼對於使用舊版本共享庫的使用者程式來說,執行時就無法找到共享庫檔案了(因為名稱已改變),還需要重新編譯連結才可以。這就這大大增加了系統維護的複雜度和成本。
於是就誕生了soname
命名機制,方便管理共享庫的版本。
此機制設計了3類命名方式:
realname
- 形如
libname.so.x.y.z
,x,y,z
分別代表主版本號,次版本號和釋出版本號。 - 一般擁有此名稱的檔案就是共享庫的原始檔
- 在庫檔案生成時使用下面命令可以指定realname:
gcc -shared -o $(realname) $(dependencies) $(flags)
soname
- 形如
libname.so.x
,x
代表主版本號 - 作用於使用者程式執行時的載入階段,動態連結器會根據使用者程式編譯時記錄的
soname
查詢對應的共享庫檔案 - 通常是
$(realname)
檔案的軟連結,在庫安裝或更新後由庫的維護者或系統管理員透過包管理器更新軟連結的指向,一般不由單個使用者手動進行軟連結。 - 在庫檔案生成時使用下面命令可以指定其
soname
:gcc -shared -o $(realname) $(dependencies) $(flags) −Wl,−soname,$(soname)
- 對於一個共享庫檔案,我們可以透過
readelf -d
命令檢視其soname
linkname
- 形如
libname.so
,是沒有任何版本編號的檔名 - 作用於使用者程式編譯階段,連結器使用
linkname
來尋找對應的共享庫(GCC中使用-l選項指定庫,如-laaa
,連結器就會去找libaaa.so
),然後將共享庫的soname
記錄在使用者程式的動態連結資訊中。 - 通常是
$(realname)
檔案或$(soname)
檔案的軟連結,在庫安裝或更新後由庫的維護者或系統管理員透過包管理器更新軟連結的指向,一般不由單個使用者手動進行軟連結。
總結
總的來說,對於Linux下的使用者程式,soname命名機制主要參與了以下兩個過程:
①連結階段:連結器按照搜尋路徑優先順序,根據linkname
去找對應的.so
檔案,如果找到了就會在生成的可執行檔案中記錄.so
檔案指向的共享庫檔案的soname
;如果沒有找到就會去找靜態庫檔案選擇靜態連結。
②載入階段:程式執行時,動態連結器按照搜尋路徑優先順序,根據可執行檔案中記錄的soname
去找對應的*.so.x
檔案,如果找到了就會載入其指向的共享庫;沒找到就報錯。
這樣的處理確保了應用程式在執行時能夠找到合適的庫版本,同時允許系統管理員在不影響已有應用程式的情況下更新庫檔案。
參考文章
1.Linux下動態連結庫檔案的realname、soname和linkname
2.Program Library HOWTO-Shared Libraries
3.Shared objects: sonames, real names, and link names
4.Linux 共享庫的 soname 命名機制