本文主要介紹在linux作業系統中,同乙個共享庫(so)的幾個名稱,以及這幾個名稱的應用場景。
本文從共享庫(so)的版本控制角度來講述。本文會以 curl 共享庫 libcurl 為例,來展開講述。
首先在此說明,so有三個名字,如下:
realname是so的真實名稱,如編譯安裝curl軟體後,生成的 /usr/local/lib/libcurl.so.4.5.0。
realname在檔名中帶有版本號資訊,如 libcurl.so.4.5.0 的「4.5.0」。
從版本控制的指令碼來看,如果乙個可執行程式直接連線到so的realname,那麼當該so公升級的時候,so的版本號發生了變化,那麼就必須重新編譯生成該可執行程式,這顯然是不好的版本管理方式。為了解決此問題,出現了so的soname。soname實際上是realname的乙個軟鏈結,我們可以通過「readelf -d」命令檢視so的soname,如下:
soname一般會保留so的大版本號,如 libcurl.so.4。
在編譯生成程式(可執行程式及共享庫)時,我們通常都是連線的soname,這樣當被依賴的so公升級時,由於soname並沒有變化,只需要將soname指向新的realname,即可實現被依賴的so的公升級了,如此就實現了so的版本控制。
linkername是編譯**時的連線階段使用的so的名字,實際上linkername也是指向realname的。
一般在程式編譯時,我們會通過 -l 選項為其指定需要連線的so的名字(或是使用cmakelists.txt時,為其指定的so的名字),樣式類似:
-lcurl
或對應cmakelists.txt中的「target_link_libraries(目標程式 ... curl ...)」,這裡的 curl 就是so的linkername。
在編譯生成程式時使用linkername進行連線的,而這個linkername實際上是指向 realname 的,但是在後續的使用過程中,程式其實是使用 soname 來找到被依賴的 realname 的,那麼這三者是如何在編譯、使用過程中連線起來的呢?
原來在編譯生成 realname 時,已經為其指定了對應的 soname (如前文所述,可通過「readelf -d」來查詢),這樣以 soname 作為橋梁,即可將so的三個名稱聯絡起來。
結合程式的編譯、生成、執行過程,描述so的三個名稱關係如下:
1. 程式編譯時,用到了依賴庫的so的 linkername,即 curl,由於 linkername 指向 realname,所以程式實際上連線到了 realname;
2. 程式從 realname 處獲取到執行時需要用到的 soname,即 libcurl.so.4;
3. 編譯生成程式;
4. 程式執行時,呼叫 soname,而 soname 實際上又指向了 realname,所以程式實際上是呼叫的 realname。
上述幾個步驟可以使用下圖來表述:
lLinux中共享庫的組織
相容性 相容更新 所有更新只是在原有的基礎上新增或修改一些內容,所有介面都保持不變。不相容更新 改變了原有的介面,使用該共享庫原有介面的程式可能不能正常執行。導致不相容的有以下幾種情況 命名 規則如下 libname.so.x.y.z glibc並沒有遵守這個規則,而是libc x.y.z.so s...
Linux下共享庫(SO)有關的幾個環境變數
linux 支援共享庫已經有悠久的歷史了,不再是什麼新概念了。大家都知道如何編譯 連線以及動態載入 dlopen dlsym dlclose 共享庫。但是,可能很多人,甚至包括一些高手,對共享庫相關的一些環境變數認識模糊。當然,不知道這些環境變數,也可以用共享庫,但是,若知道它們,可能就會用得更好。...
Linux下共享庫(SO)有關的幾個環境變數
linux支援共享庫已經有悠久的歷史了,不再是什麼新概念了。大家都知道如何編譯 連線以及動態載入 dlopen dlsym dlclose 共享庫。但是,可能很多人,甚至包括一些高手,對共享庫相關的一些環境變數認識模糊。當然,不知道這些環境變數,也可以用共享庫,但是,若知道它們,可能就會用得更好。下...