Ict-創新/LPI/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 的內容。
| $ 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 /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