共享庫連結和載入時的路徑搜尋優先順序

paw5zx發表於2024-07-15

目錄
  • 前言
  • 共享庫的連結
  • 共享庫的載入

前言

在開發一個新專案時遇到了共享庫衝突的問題,因此在這裡記錄一下共享庫的連結和載入過程中庫路徑的搜尋優先順序的相關知識。

共享庫的連結

現在有一個main.o可重定位目標檔案,其中需要用到開源庫log4cpp。在連結的時候,我們可以這樣連結:

g++ main.o -o a.out -L/path/to/libs -llog4cpp

其中:
-L/path/to/libs表示連結器去哪個目錄下查詢庫檔案。
注意:透過-L指定的路徑的搜尋優先順序是要高於系統預設的庫檔案路徑的。

編譯時庫搜尋優先順序:
-L指定的路徑> LIBRARY_PATH>預設庫路徑

-llog4cpp表示要連結的庫,在連結階段,連結器一般會按照搜尋優先順序,從庫路徑中查詢名為liblog4cpp.soliblog4cpp.a的檔案進行連結。若不特殊說明,預設優先連結共享庫。

共享庫的載入

在程式開始執行前的載入階段,動態連結器會讀取可執行檔案,查詢並載入所有必須的共享庫。注意此時的搜尋路徑並不包含/path/to/libs,因為它只作用於連結階段。連結器搜尋的路徑有:LD_LIBRARY_PATH環境變數,/etc/ld.so.cache檔案,預設庫路徑(/usr/lib,/lib等)。

如果需要從指定的路徑載入共享庫,則可以使用下述方法:

  • 手動設定LD_LIBRARY_PATH環境變數:在程式執行前設定環境變數,指定共享庫的搜尋路徑:
    export LD_LIBRARY_PATH=/path/to/runtime_libs:$LD_LIBRARY_PATH
    
    注意,此方法設定環境變數是臨時的,一旦終端關閉設定就會失效。若想使其持久化,需要特殊設定,方法包括但不限於:修改.bashrc檔案,修改rc.loacl檔案。
  • 修改/etc/ld.so.conf/etc/ld.so.conf.d/*配置:
    這些檔案提供了系統級別的庫搜尋路徑。系統管理員可以在這些檔案中定義預設的庫搜尋路徑,這些設定對所有使用者和應用程式都有效。
  • 在連結階段使用-rpath:
    在連結階段,設定RPATH或RUNPATH,將庫路徑硬編碼到可執行檔案中
    g++ main.o -o a.out -L/path/to/libs -llog4cpp -Wl,-rpath,/path/to/runtime_libs
    
    注意若可執行檔案中同時包含RPATH和RUNPATH,那麼RPATH將會被動態連結器忽略。

共享庫的搜尋優先順序為:
RPATH>LD_LIBRARY_PATH>RUNPATH>/etc/ld.so.conf/etc/ld.so.conf.d/*>預設庫路徑

相關文章