Linux 系統上有兩類根本不同的 Linux 可執行程式。第一類是靜态連結的可執行程式。靜态可執行程式包含執行所需的所有函數 —
換句話說,它們是“完整的”。因為這一原因,靜态可執行程式不依賴任何外部庫就可以運作。
第二類是動态連結的可執行程式。
靜态可執行程式與動态可執行程式比較
我們可以用 ldd
指令來确定某一特定可執行程式是否為靜态連結的:
# ldd /sbin/sln
not a dynamic
executable
“not a dynamic executable”是 ldd 說明 sln 是靜态連結的一種方式。現在,讓我們比較 sln
與其非靜态同類 ln 的大小:
# ls -l /bin/ln
/sbin/sln
-rwxr-xr-x 1
root root 23000
Jan 14 00:36 /bin/ln
root root 381072
Jan 14 00:31 /sbin/sln
如您所見,sln 的大小超過 ln 十倍。ln 比 sln
小這麼多是因為它是動态可執行程式。動态可執行程式是不完整的程式,它依靠外部共享庫來提供運作所需的許多函數。
動态連結相關性
要檢視 ln 依賴的所有共享庫的清單,可以使用 ldd 指令:
# ldd /bin/ln
libc.so.6 =>
/lib/libc.so.6 (0x40021000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2
(0x40000000)
如您所見,ln 依賴外部共享庫 libc.so.6 和
ld-linux.so.2。通常,動态連結的程式比其靜态連結的等價程式小得多。不過,靜态連結的程式可以在某些低級維護任務中發揮作用。例如,sln 是修改位于
/lib 中的不同庫符号連結的極佳工具。但通常您會發現幾乎所有 Linux 系統上的可執行程式都是某種動态連結的變體。
動态裝入器
那麼,如果動态可執行程式不包含運作所需的所有函數,Linux
的哪部分負責将這些程式和所有必需的共享庫一起裝入,以使它們能正确執行呢?答案是動态裝入器(dynamic loader),它實際上是您在 ln 的 ldd
清單中看到的作為共享庫相關性列出的 ld-linux.so.2
庫。動态裝入器負責裝入動态連結的可執行程式運作所需的共享庫。現在,讓我們迅速檢視一下動态裝入器如何在系統上找到适當的共享庫。
ld.so.conf
動态裝入器找到共享庫要依靠兩個檔案 — /etc/ld.so.conf 和 /etc/ld.so.cache。如果您對 /etc/ld.so.conf
檔案進行 cat 操作,您可能會看到一個與下面類似的清單:
$ cat /etc/ld.so.conf
/usr/X11R6/lib
/usr/lib/gcc-lib/i686-pc-linux-gnu/2.95.3
/usr/lib/mozilla
/usr/lib/qt-x11-2.3.1/lib
/usr/local/lib
ld.so.conf 檔案包含一個所有目錄(/lib 和 /usr/lib 除外,它們會自動包含在其中)的清單,動态裝入器将在其中查找共享庫。
ld.so.cache
但是在動态裝入器能“看到”這一資訊之前,必須将它轉換到 ld.so.cache 檔案中。可以通過運作 ldconfig 指令做到這一點:
# ldconfig
ldconfig指令的用途,
主要是在預設搜尋目錄(/lib和/usr/lib)以及動态庫配置檔案/etc/ld.so.conf内所列的目錄下,
搜尋出可共享的動态連結庫(格式如lib*.so*), 進而建立出動态裝入程式(ld.so)所需的連接配接和緩存檔案.
緩存檔案預設為/etc/ld.so.cache,
此檔案儲存已排好序的動态連結庫名字清單.
這裡面涉及到的關鍵内容有指令:ldconfig,配置檔案目錄:/etc/ld.so.conf.d,配置檔案在/etc/ld.so.conf内容由使用者編輯,緩沖檔案/etc/ld.so.cache。下面舉個例子,比如你在部署軟體時,有些動态庫安裝在exe目錄下,可以通過如下方法實作,
1)配置exe.conf檔案,裡面加一行~/exe,然後将該檔案放到/etc/ld.so.conf.d目錄下;
2)在/etc/ld.so.conf檔案中增加一行include
ld.so.conf.d/exe.conf
3)執行
ldconfig指令
之後程式運作時,會自動增加在exe目錄中搜尋動态庫。
當 ldconfig 操作結束時,您會有一個最新的 /etc/ld.so.cache 檔案,它反映您對 /etc/ld.so.conf
所做的更改。從這一刻起,動态裝入器在尋找共享庫時會檢視您在 /etc/ld.so.conf 中指定的所有新目錄。
ldconfig 技巧
要檢視 ldconfig 可以“看到”的所有共享庫,請輸入:
# ldconfig -p | less
還有另一個友善的技巧可以用來配置共享庫路徑。有時候您希望告訴動态裝入器在嘗試任何 /etc/ld.so.conf
路徑以前先嘗試使用特定目錄中的共享庫。在您運作的較舊的應用程式不能與目前安裝的庫版本一起工作的情況下,這會比較友善。
LD_LIBRARY_PATH
要訓示動态裝入器首先檢查某個目錄,請将 LD_LIBRARY_PATH 變量設定成您希望搜尋的目錄。多個路徑之間用冒号分隔;例如:
# export LD_LIBRARY_PATH="/usr/lib/old:/opt/lib"
導出 LD_LIBRARY_PATH 後,如有可能,所有從目前 shell 啟動的可執行程式都将使用 /usr/lib/old 或 /opt/lib
中的庫,如果仍不能滿足一些共享庫相關性要求,則轉回到 /etc/ld.so.conf 中指定的庫。