跳轉到內容

Ict-創新/LPI/102.3

來自華夏公益教科書,開放的世界,開放的書籍

102.3 管理共享庫

[編輯 | 編輯原始碼]

候選人應該能夠確定可執行程式依賴的共享庫,並在必要時安裝它們。


關鍵知識領域

  • 識別共享庫
  • 識別系統庫的典型位置。
  • 載入共享庫。

庫是一組函式,程式可以使用這些函式來實現它們的功能。在構建(連結)程式時,這些庫可以靜態或動態連結到可執行檔案。靜態連結意味著最終程式將在其檔案中包含庫函式。(lib.a)動態連結意味著當程式執行時,所需的庫將載入到 RAM 中(lib.so)。


在編寫應用程式時,開發人員會使用現有的軟體庫來提供應用程式所需的 functionality。當最終應用程式被編譯時,有兩種選擇可用。

  • 使用所有必需的庫編譯到應用程式中構建應用程式。這被稱為將庫靜態連結到應用程式。這樣做的好處是應用程式安裝後不會出現依賴性問題,但缺點是二進位制檔案的大小會增加,因為庫在每個靜態連結庫的應用程式中都重複。最負面的影響是,核心無法透過僅載入一次重複程式碼來最佳化記憶體。相反,每個應用程式都載入了相同的程式碼。
  • 在執行時動態連結所需的依賴項。動態連結的可執行檔案比靜態連結程式小得多,因為它們不包含它們所依賴的庫程式碼。使用動態連結允許執行使用相同庫的程式來共享該庫的一個副本,而不是佔用記憶體來儲存重複的副本。由於庫程式碼是獨立的,因此 Linux 發行版的包管理系統可以獨立於應用程式更新庫程式碼。由於這些原因,如今大多數程式都使用動態連結。

為了在執行時查詢應用程式所需的庫,Linux 需要知道在哪裡查詢它們。預設情況下,Linux 在以下受信任位置查詢庫檔案

  • /lib: - 主要由 /bin 程式使用。
  • /usr/lib - 主要由 /usr/bin 程式使用。

庫檔案的其他位置可以在 /etc/ld.so.conf 檔案中指定。ld.so.conf 檔案可以包含 /etc/ld.so.conf.d 目錄下的所有檔案,具體取決於您的發行版。列表 5 顯示了 64 位 Fedora 12 系統上的 /etc/ld.so.conf 的內容。

/etc/ld.so.conf 的內容


$ cat /etc/ld.so.conf

include ld.so.conf.d/*.conf

$ 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 檔案中的目錄和受信任目錄,以在 /etc/ld.so.cache 中建立一個快速快取。

當應用程式啟動時,動態載入器使用 ld.so.cache 中的快取資訊來定位檔案。對 ld.so.conf 檔案的任何更改都需要執行 ldconfig 命令來更新 /etc/ld.so.cache 檔案。


ldd 命令

[編輯 | 編輯原始碼]

如果您想了解應用程式是靜態連結的,還是動態連結應用程式的依賴項是什麼,您可以使用 ldd 命令。例如 ldd /usr/sbin/apache 顯示以下內容


ldd /usr/sbin/apache2

linux-vdso.so.1 => (0x00007ffff85ff000)

libpcre.so.3 => /lib/libpcre.so.3 (0x00007feeaf2e4000)

libaprutil-1.so.0 => /usr/lib/libaprutil-1.so.0 (0x00007feeaf0c1000)

libapr-1.so.0 => /usr/lib/libapr-1.so.0 (0x00007feeaee8b000)

libpthread.so.0 => /lib/libpthread.so.0 (0x00007feeaec6e000)

libc.so.6 => /lib/libc.so.6 (0x00007feeae8eb000)

libuuid.so.1 => /lib/libuuid.so.1 (0x00007feeae6e5000)

librt.so.1 => /lib/librt.so.1 (0x00007feeae4dd000)

libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007feeae2a4000)

libdl.so.2 => /lib/libdl.so.2 (0x00007feeae09f000)

libexpat.so.1 => /lib/libexpat.so.1 (0x00007feeade76000)

/lib64/ld-linux-x86-64.so.2 (0x00007feeaf7ab000)

這告訴我們 apache2 是動態連結的,並依賴於列出的庫。如果缺少庫,ldd 將使用“未找到”一詞輸出依賴項。這在排查依賴性問題時很有用。


LD_LIBRARY_PATH

有時您可能需要覆蓋動態庫的預設搜尋路徑。這可能是為了您從原始碼安裝的應用程式,為了測試最新版本的庫,或者如果應用程式依賴於您已安裝在機器上的舊版本的庫。

要將庫新增到搜尋路徑,您需要定義和匯出 LD_LIBRARY_PATH 變數,如下所示


# export LD_LIBRARY_PATH=/usr/lib/:/opt/someapp/lib;

LD_LIBRARY_PATH 是一個冒號分隔的目錄列表,在 ld.so.cache 中指定的系統目錄之前搜尋這些目錄。這允許臨時覆蓋在 ld.so.cache 和受信任目錄中定義的庫。



使用的檔案、術語和實用程式

  • ldd
  • ldconfig
  • /etc/ld.so.conf
  • LD_LIBRARY_PATH


上一章 | 下一章

華夏公益教科書