在本文中,學(xué)習(xí)如何找到并加載 Linux 可執(zhí)行程序所需的共享庫。您將學(xué)到:
本文將幫助您準(zhǔn)備 Linux Professional Institute's Junior Level Administration (LPIC-1) 考試 101 中主題 102 下的目標(biāo) 102.3。該目標(biāo)的權(quán)值為 1。
為了更有效利用這部分內(nèi)容,您需要具有基本的 Linux 知識,并需要準(zhǔn)備一個(gè) Linux 系統(tǒng),用于練習(xí)本文介紹的命令。有時(shí)候不同版本的程序輸出格式不同,因此您所得到的結(jié)果未必總是與此處的相同。特別要指出,這里的很多例子來自 64 位系統(tǒng)。我們引入了很多來自 32 位系統(tǒng)的例子,來說明兩者的顯著差異 。
Linux 系統(tǒng)當(dāng)中有兩類可執(zhí)行程序:
在許多 Linux 系統(tǒng)中有個(gè)很有趣的例子,ln
命令(/bin/ln),用于在文件之間生成鏈接,不論是 硬 鏈接還是 軟 (或者 符號 )鏈接。 該命令使用共享庫。共享庫經(jīng)常會引入庫通用名與庫特定層級之間的符號鏈接,所以如果因?yàn)槟承┰蜴溄記]有出現(xiàn)或已斷開,那么 ln
命令本身就無法起作用,會發(fā)生循環(huán)錯(cuò)誤。為避免此類問題,一些 Linux 系統(tǒng)包含了ln
sln
(/sbin/sln)之間的靜態(tài)鏈接版本。清單 1 說明了采用動態(tài)鏈接的ln
與采用靜態(tài)鏈接的sln
之間大小的顯著差別。該例子來自 Fedora 12 64-bit 系統(tǒng)。
|
盡管當(dāng)前的 LPI 考試不涉及此類問題,但您還是應(yīng)當(dāng)明確當(dāng)今很多 Linux 系統(tǒng)所運(yùn)行的硬件同時(shí)支持 32 位及 64 位程序。很多庫同時(shí)編譯為 32 位及 64 位版本。64 位版本通常存放在文件系統(tǒng)的 /lib64 目錄樹中,而 32 位版本則位于 /lib 目錄樹中。您可能會在 64 位 Linux 系統(tǒng)中同時(shí)發(fā)現(xiàn) /lib/libc-2.11.1.so 以及 /lib64/libc-2.11.1.so 。這兩個(gè)庫允許 32 位及 64 位 C 程序在 64 位 Linux 系統(tǒng)當(dāng)中運(yùn)行。
除了明確靜態(tài)鏈接程序比較大之外,如何確定程序是否為靜態(tài)鏈接?如果是靜態(tài)鏈接,如何知道它需要哪些庫?ldd
命令能夠回答這些問題。如果您正在運(yùn)行 Debian 或 Ubuntu之類的程序,可能找不到 sln 命令,因此您可能會檢查 /sbin/ldconfig 能否執(zhí)行。清單 2 展示了ldd
命令關(guān)于 ln 以及 sln 執(zhí)行情況,還有 ldconfig 可執(zhí)行情況的輸出。該例子來自 Fedora 12 64-bit 系統(tǒng)(echidna)。為了進(jìn)行對比,還列出了來自舊版本 Fedora 8 32-bit 系統(tǒng)(pinguino)關(guān)于 /bin/ln 的輸出 。
ldd
關(guān)于 sln 以及 ln 的輸出
|
因?yàn)?ldd
與動態(tài)鏈接有關(guān),這告訴我們 sln 與 ldconfig 都是靜態(tài)鏈接的,它們 “不是一個(gè)動態(tài)可執(zhí)行文件”,同時(shí)告訴我們 ln
命令所需共享庫的名字(linux-vdso.so.1、libc.so.6 和 /lib64/ld-linux-x86-64.so.2)。注意, .so 指明這些是 共享庫 或者動態(tài)庫。這一輸出結(jié)果提供了您想了解的三類不同信息。
在清單 3 中,通過 ls -l
命令,發(fā)現(xiàn)最后的兩個(gè)庫依次與庫的特定版本之間具有符號鏈接。該例子來自 Fedora 12 64-bit系統(tǒng) 。
|
Linux Virtual Dynamic SharedObjects
在早期的 x86 處理器中,用戶程序與管理服務(wù)之間的通信通過軟中斷實(shí)現(xiàn)。隨著處理器速度的提高,這已成為一個(gè)嚴(yán)重的瓶頸。自 Pentium? II 處理器開始,Intel? 引入了 FastSystem Call 裝置來提高系統(tǒng)調(diào)用速度,即采用 SYSENTER 和 SYSEXIT 指令,而不是中斷。
您所看到的 linux-vdso.so.1 是個(gè)虛擬庫,或者說是 Virtual Dynamic Shared Object ,它只存在于程序的地址空間當(dāng)中。在舊版本系統(tǒng)中該庫為 linux-gate.so.1。該虛擬庫為用戶程序以處理器可支持的最快的方式(對于特定處理器,采用中斷方式;對于大多數(shù)最新的處理器,采用快速系統(tǒng)調(diào)用方式)訪問系統(tǒng)函數(shù)提供了必要的邏輯 。
通過前面的內(nèi)容,您會很奇怪的發(fā)現(xiàn)/lib/ld-linux.so.2 以及它的 64 位版本,/lib64/ld-linux-x86-64.so.2,看上去都像是共享庫,都在其各自的權(quán)限內(nèi)可執(zhí)行。它們是負(fù)責(zé)實(shí)現(xiàn)動態(tài)加載的代碼。它們讀取可執(zhí)行程序的頭信息,這些信息采用 Executable andLinking Format 或者( ELF )格式。它們通過這些消息,來確定哪些庫是必須的,以及哪些庫需要加載。然后執(zhí)行動態(tài)鏈接,把可執(zhí)行程序當(dāng)中所有的地址指針與需要加載的庫聯(lián)系起來,這樣程序就可以運(yùn)行了。
有關(guān) ld-linux.so 的幫助也描述了 ld.so,它為早期的 a.out 二進(jìn)制格式提供類似的功能。清單 4 舉例說明,如何利用 ld-linux.so 的 --list
選項(xiàng)來顯示與清單 2 當(dāng)中ln
命令與 ldd
命令顯示結(jié)果相同的內(nèi)容。
|
注意,兩個(gè)清單中的十六進(jìn)制地址有可能不同。在兩次運(yùn)行 ldd
命令時(shí),該地址也可能不相同。
動態(tài)加載器怎樣找到可執(zhí)行程序?對于 Linux 當(dāng)中的很多問題,都在 /etc 當(dāng)中有相應(yīng)的配置文件。事實(shí)上,有兩個(gè)配置文件,/etc/ld/so/conf 以及 /etc/ld.so.cache。清單 5 展示了 Fedora 12 64 位系統(tǒng)當(dāng)中 /etc/ld.so.conf 的內(nèi)容。注意,/etc/ld.so.conf 文件指明所有來自 ld.so.conf.d 子目錄的 .conf 文件都應(yīng)當(dāng)被包含。舊版系統(tǒng)中可能包含 /etc/ld/so/conf 的所有條目,而不包含 /etc/ld.so.conf.d 目錄中的條目。您的系統(tǒng)當(dāng)中 /etc/ld.so.conf 或者 /etc/ld.so.conf.d 目錄的實(shí)際內(nèi)容可能與此處有所差別。
|
程序需要快速加載,因此可以使用ldconfig
命令來處理 ld.so.conf 文件、所有 ld.so.conf.d 包含的文件、所有受信目錄當(dāng)中的庫、/lib 和 /usr/lib,以及命令行當(dāng)中所支持的其他內(nèi)容 。ldconfig
命令在 /etc/ld.so.cache 中為最近使用過的共享庫生成必須的鏈接和 cache 。動態(tài)加載器利用來自 ld.so.cache 的緩存文件來定位需要?jiǎng)討B(tài)加載及鏈接的文件。如果改變了 ld.so.conf(或在 ld.so.conf.d 中增加新文件),必須運(yùn)行 ldconfig
命令(以 root 用戶身份)來重構(gòu) ld.so.cache 文件。
通常,可在不加參數(shù)的情況下,使用 ldconfig 命令來重構(gòu) ld.so.cache 文件??梢岳靡恍﹨?shù)來改變這一使用習(xí)慣。一般情況下,可使用 man ldconfig
來獲得更多信息。清單 6 舉例說明利用參數(shù) -p
來展示 ld.so.cache 的內(nèi)容。
|
如果您正在運(yùn)行需要特定舊版共享庫支持的程序,或者您正在開發(fā)新的共享庫或現(xiàn)有共享庫的新版本,您可能希望覆蓋加載器的默認(rèn)搜索路徑。使用安裝在 /opt 樹當(dāng)中特定于產(chǎn)品共享庫的腳本文件可能也需要這一功能。
就如同可通過設(shè)置變量 PATH 來為可執(zhí)行程序指定搜索路徑一樣,可以將變量 LD_LIBRARY_PATH 設(shè)置為用冒號分割的,為加載 ld.so.cache 當(dāng)中所指定的共享庫需要搜索的目錄清單。例如,可使用命令:
export LD_LIBRARY_PATH=/usr/lib/oldstuff:/opt/IBM/AgentController/lib |
參見下面的 參考資料 來獲得細(xì)節(jié)信息以及相關(guān)文章的鏈接。
學(xué)習(xí)
獲得產(chǎn)品和技術(shù)
討論
IanShields 參與 developerWorks Linux 專區(qū)的許多 Linux 項(xiàng)目。他是 IBM 北卡羅來納州 ResearchTriangle Park 的一名高級程序員。他于 1973 年作為一名系統(tǒng)工程師加入 IBM位于澳大利亞堪培拉的子公司。此后,在加拿大蒙特利爾和北卡羅來納州 RTP 從事通信系統(tǒng)和普適計(jì)算。他擁有多項(xiàng)專利。他畢業(yè)于 AustralianNational University,本科學(xué)位是純粹數(shù)學(xué)和哲學(xué)。他擁有北卡羅來納州州立大學(xué)的計(jì)算機(jī)碩士和博士學(xué)位。