IBM的LPI複習資料之LPI101-Topic102:Linux安裝和包管理(3)管理動態連結程式庫(尋找和載入程式需要的動態連結程式庫檔案)

來源:互聯網
上載者:User
概述本文講述如何尋找和載入Linux應用程式需要的動態庫。具體是:
  • 確定程式需要的庫檔案
  • 系統如何尋找共用庫檔案
  • 載入共用庫檔案
本文協助讀者準備LPI101中的102.3目標,權重為1.靜態和動態連結Linux系統裡有兩種類型的可執行程式:
  • 靜態連結的可執行程式。這種程式檔案本身包含了運行所需要的所有庫函數的代碼。程式自身就可以運行,而不依賴於額外的庫檔案。靜態連結的程式的一個優點就是安裝時不需要額外安裝依賴庫。
  • 動態連結的可執行程式。動態連結程式只為調用的庫函數設定了預留位置,並沒有真正把函數代碼連結到程式本身中,所以這種程式體積小。而且往往多個程式依賴於同一個共用庫檔案,這樣多個程式運行時,通過虛擬記憶體的機制,實體記憶體中之需要保留一份共用庫代碼,大大節約了記憶體空間。其缺點是自身運行需要依賴外部庫檔案,安裝時如果所依賴的庫檔案不存在,需要額外安裝庫檔案。總的來說,其優點大於缺點,所以目前系統上大多數程式都是動態連結的。
在許多Linux系統中存在一個有趣的例子:/bin/ln命令。這個命令用來建立軟連結或者永久連結(注意此處的連結與程式的動態連結是兩個不同的概念)。ln這個程式也是動態連結的,所以其運行依賴動態載入機制。載入動態庫時往往使用的是符號連結(比如使用ls-linux-86-64.so.2這個符號連結而不是真正的檔案ld-2.11.1.so),所以動態載入依賴於這種符號連結機制。想想如果這個軟連結有問題或者被刪除了,該怎麼辦呢?解決方式就是重建立一個。此時問題來了,為能動態載入而建立連結檔案使用的是ln命令,而ln本身運行時的動態載入又可能依賴於這個出問題符號連結,這就容易陷入死迴圈了。為瞭解決這個問題,一些Linux發行版裡額外提供了ln的靜態連結版本sln。Fedora12
64bit系統中的這兩個檔案如下所示:Listing 1. Sizes of sln and ln

[ian@echidna ~]$ ls -l /sbin/sln /bin/ln-rwxr-xr-x. 1 root root  47384 2010-01-12 09:35 /bin/ln-rwxr-xr-x. 1 root root 603680 2010-01-04 09:07 /sbin/sln

可以看出,同樣的程式靜態連結時,檔案體積要大很多。

需要哪些庫檔案?儘管LPI考試並沒有要求這個話題,你仍然應該知道現在很多的Linux系統所在的機器能夠同時支援32位和64位程式的運行。因此,很多庫檔案都同時存在32位和64位兩個版本。其中的64位版本存放在目錄/lib64中,32位版本存放在/lib中。你很可能會在一個典型的64位Linux系統中發現同時存在/lib/libc-2.11.1.so and /lib64/libc-2.11.1.so這兩個庫檔案。ldd命令除了知道一個靜態連結的檔案體積大之外,你能分辨一個程式到底是靜態連結還是動態連結的嗎?如果是動態連結的,你知道它依賴於哪些庫檔案嗎?ldd命令可以協助你回答這兩個問題。如果你正在運行一個像Debian或Ubuntu這樣的系統,你可能找不到sln程式,你也需要檢查一下/sbin/ldconfig是否存在。本例子使用的是Fedora12 64位系統。為了做個對比,32位系統上的輸出也同時列出。Listing 2. Output of  ldd for
sln and ln

                    [ian@echidna ~]$ #Fedora 12 64-bit[ian@echidna ~]$ ldd /sbin/sln /sbin/ldconfig /bin/ln/sbin/sln:        not a dynamic executable/sbin/ldconfig:        not a dynamic executable/bin/ln:        linux-vdso.so.1 =>  (0x00007fff644af000)        libc.so.6 => /lib64/libc.so.6 (0x00000037eb800000)        /lib64/ld-linux-x86-64.so.2 (0x00000037eb400000)[ian@pinguino ~]$ # Fedora 8 32-bit[ian@pinguino ~]$ ldd /bin/ln        linux-gate.so.1 =>  (0x00110000)        libc.so.6 => /lib/libc.so.6 (0x00a57000)        /lib/ld-linux.so.2 (0x00a38000)

ldd命令的功能是查看動態連結的資訊,所以對於sln,ldconfig這樣的靜態連結程式,僅僅提示"not a dynamic executable"。而對於動態連結的ln檔案則給出了所依賴的三個動態連結程式庫檔案。.so尾碼名是shared object的意思,也稱為動態連結程式庫。上面的輸出結果還顯示了三種不同類型的依賴檔案:

  • linux-vsdo.so.1 是Linux Virtual Dynamic Shared Object,一會我們會講到這個。在Fedora8中則是 linux-gate.so.1。
  • libc.so.6 指向/lib64/libc.so.6
  • /lib64/ld-linux-x86-64.so.2 是一個庫檔案的絕對路徑
下表中,我們使用ls -l命令顯示了上面最後的兩個庫檔案其實是具體版本庫檔案的符號連結。在Fedora12系統中,結果如下:Listing 3. Library symbolic links

                    [ian@echidna ~]$ ls -l /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2lrwxrwxrwx. 1 root root 12 2010-01-14 14:24 /lib64/ld-linux-x86-64.so.2 -> ld-2.11.1.solrwxrwxrwx. 1 root root 14 2010-01-14 14:24 /lib64/libc.so.6 -> libc-2.11.1.so

Linux虛擬動態共用對象在早期X86的年代裡,使用者程式和核心空間程式的通訊是通過非強制中斷。隨著處理器速度的提高,這種方式成為了嚴重的瓶頸。從Pentium II開始,Intel引進了一種叫做Fast System Call的機制來加速系統調用的執行。這種新的方式使用的專門的SYSENTER和SYSEXIT指令而不是中斷。上面提到的linux-vdso.so.1是一個虛擬庫檔案或者虛擬動態共用對象,這個檔案駐留在每一個程式進程的地址空間。老的系統裡檔案名稱是linux-gate.so.1。這個虛擬庫提供必要的邏輯來讓使用者程式在特定的處理器上選擇最快的系統函數調用方式,也許是非強制中斷,但在大多數新的CPU中都是使用fast system call。動態載入也許你會感到奇怪,上面提到的/lib/ld-linux.so.2以及它的64位版本/lib64/ld-linux-x86-64.so.2雖然看起來是共用庫檔案,但實際上他們可以獨立運行。他們的功能是負責動態載入。它們通過讀取可執行檔的頭部資訊來確定哪些庫檔案是必須的,以及哪些需要載入。載入完成後,它會通過修正執行檔案裡的相關的地址指標來和載入的庫檔案完成動態連結,此時程式就可以運行了。ld-linux.so的協助手冊還描述了ld.so這個檔案,ld.so針對的是早期的a.out格式的可執行程式。ld-linux.so.2的--list參數可以顯示和ldd命令同樣的資訊,如下表:Listing 4. Using ld-linux.so to display library requirements

                    [ian@echidna ~]$ /lib64/ld-linux-x86-64.so.2 --list /bin/ln        linux-vdso.so.1 =>  (0x00007fffc9fff000)        libc.so.6 => /lib64/libc.so.6 (0x00000037eb800000)        /lib64/ld-linux-x86-64.so.2 (0x00000037eb400000)[ian@pinguino ~]$ /lib/ld-linux.so.2 --list /bin/ln        linux-gate.so.1 =>  (0x00110000)        libc.so.6 => /lib/libc.so.6 (0x00a57000)        /lib/ld-linux.so.2 (0x00a38000)

注意:上面的地址部分可能每次運行都會有所不同。動態庫配置從可執行檔頭可以讀取依賴的庫檔案資訊,那麼動態載入器去哪裡尋找這些庫檔案呢?還是Linux世界的慣例,存在一個設定檔描述這些資訊。實際上,有兩個設定檔,一個是/etc/ld.so.conf,另一個是/etc/ld.so.cache。下表顯示了/etc/ld.so.conf的內容。注意/etc/ld.so.conf檔案指定了ld.so.conf.d目錄下的所有設定檔都會被包含進來。老系統上的/etc/ld.so.conf檔案可能本身就包含了很多配置項而不是從子目錄中載入配置項。Listing 5. Content of /etc/ld.so.conf

                    [ian@echidna ~]$ cat /etc/ld.so.confinclude ld.so.conf.d/*.conf[ian@echidna ~]$ ls /etc/ld.so.conf.d/*.conf/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.19.fc12.x86_64.conf/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.22.fc12.x86_64.conf/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.3.fc12.x86_64.conf/etc/ld.so.conf.d/mysql-x86_64.conf/etc/ld.so.conf.d/qt-x86_64.conf/etc/ld.so.conf.d/tix-x86_64.conf/etc/ld.so.conf.d/xulrunner-64.conf

程式的載入速度很重要,所以使用ldconfig命令來處理ld.so.conf檔案以及它包含的其他設定檔,還有/lib, /usr/lib目錄下的庫檔案,以及以命令列參數形式提供的其他庫檔案。ldconfig的作用是為最近使用的庫檔案建立必要的符號連結和緩衝資訊,並寫入/etc/ld.so.cache檔案。動態載入器利用/etc/ld.so.cache這個檔案裡的資訊來尋找和載入庫檔案。如果你改變了ld.so.conf檔案或者其包含的子檔案,你必須重新運行ldconfig命令來更新/etc/ld.so.cache快取檔案。正常情況下,你使用不帶任何參數的ldconfig命令來重建ld.so.cache檔案。你也可以為ldconfig提供命令來改變這種預設的行為。通常使用man ldconfig來查看更多地資訊。下表顯示了使用-p 參數來查看ld.so.cache裡的內容。Listing 6. Using ldconfig to display ld.so.cache

                    [ian@lyrebird ian]$ /sbin/ldconfig -p | less1602 libs found in cache `/etc/ld.so.cache'        libzip.so.1 (libc6,x86-64) => /usr/lib64/libzip.so.1        libz.so.1 (libc6,x86-64) => /lib64/libz.so.1        libz.so (libc6,x86-64) => /usr/lib64/libz.so        libx86.so.1 (libc6,x86-64) => /usr/lib64/libx86.so.1        libx11globalcomm.so.1 (libc6,x86-64) => /usr/lib64/libx11globalcomm.so.1        libxul.so (libc6,x86-64) => /usr/lib64/xulrunner-1.9.1/libxul.so        libxtables.so.2 (libc6,x86-64) => /usr/lib64/libxtables.so.2        libxslt.so.1 (libc6,x86-64) => /usr/lib64/libxslt.so.1        libxslt.so (libc6,x86-64) => /usr/lib64/libxslt.so        libxpcom.so (libc6,x86-64) => /usr/lib64/xulrunner-1.9.1/libxpcom.so        libxml2.so.2 (libc6,x86-64) => /usr/lib64/libxml2.so.2        libxml2.so (libc6,x86-64) => /usr/lib64/libxml2.so       ...        libABRTdUtils.so.0 (libc6,x86-64) => /usr/lib64/libABRTdUtils.so.0        libABRTUtils.so.0 (libc6,x86-64) => /usr/lib64/libABRTUtils.so.0        ld-linux.so.2 (ELF) => /lib/ld-linux.so.2        ld-linux-x86-64.so.2 (libc6,x86-64) => /lib64/ld-linux-x86-64.so.2
載入指定的庫檔案如果你在運行一個依賴於特定老版本共用庫檔案的應用程式,或者你在開發測試一個新開發的共用庫或者已存在共用庫的新版本,你就需要載入器使用的預設尋找路徑。這種需要也出現在使用特定產品共用庫的指令碼中,這個特定的產品共用庫可能安裝到了/opt目錄下。就像可以通過修改PATH環境變數來指定可執行程式的搜尋路徑一樣,你可以通過修改LD_LIBRARY_PATH環境變數來修改動態載入器的尋找路徑。LD_LIBRARY_PATH指定的路徑會排在ld.so.cache檔案裡的路徑之前。例如,你可能會使用這樣一些命令:
export LD_LIBRARY_PATH=/usr/lib/oldstuff:/opt/IBM/AgentController/lib

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.