Linux動態庫的查詢路徑

2021-07-09 05:50:49 字數 2114 閱讀 6942

前兩天寫了乙個動態庫,然後試圖編譯到程式裡面去執行,結果發現編譯的時候通過gcc的-l引數來指定路徑僅僅能讓編譯通過,執行時還是會出問題的。

比如下面這個例子:

main.c是主程式,sum.c中間含有乙個函式add,用來執行加法,**如下:

1/*2

* main.c3*/

4 #include 5

6int add(int a, int

b);7

8int main(int argc,char *argv)

9

1/*2

* sum.c3*/

4int add(int a, intb)5

出錯結果如下圖所示:

我在編譯的時候通過-l指定了查詢動態庫的位置,結果執行的時候還是找不到我自己寫的那個libsum.so這個動態庫,後來去查了一下,才明白其中原委。

程式在鏈結動態庫的時候分為2步,編譯時鏈結和執行時鏈結。

1. 編譯時鏈結

這個過程是由ld程式來執行的,所以編譯時找不到動態庫的位置的話,經常就會看到這種錯誤:

這個過程嚴格意義上來說並不能說是鏈結,因為在這裡ld程式並沒有真正的把庫裡面的函式的執行**寫到可執行檔案裡面,只是把一些符號還有其他的必要資訊寫道了可執行檔案裡面,供可執行檔案執行時查詢。

總的來說,ld在這一步裡面就是做了兩個事情:

1. 查詢動態庫中是否含有我們需要的符號(函式和全域性變數),如果都能找到,則鏈結允許通過,生成了可執行檔案。

2. 在可執行檔案中寫入了符號和其他必要的資訊(例如符號的位址),供可執行檔案執行時查詢。

2. 執行時鏈結

這個過程是由ld-linux.so程式來執行,這個才是真正的鏈結。它所做的工作就是將動態庫的**對映到程序(可執行檔案執行起來就是程序啦...)的虛擬位址空間中,供程序來呼叫。

關於鏈結,載入,執行的更多資訊可以參看《參考文章1>(詳細位址見本文最後)。

ok,明白了上面兩個鏈結之後,我們再來看這兩個鏈結查詢動態庫的目錄位置,如下:

(1)ld-linux.so.6在可執行的目標檔案中被指定,可用readelf命令檢視 

(2)ld-linux.so.6預設在/usr/lib和lib中搜尋;當glibc安裝到/usr/local下時,它查詢/usr/local/lib

(3)ld_library_path環境變數中所設定的路徑 

(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路徑,由ldconfig生成二進位制的ld.so.cache中

(1)ld-linux.so.6由gcc的spec檔案中所設定 

(2)gcc --print-search-dirs所列印出的路徑,主要是libgcc_s.so等庫。可以通過gcc_exec_prefix來設定 

(3)library_path環境變數中所設定的路徑,或編譯的命令列中指定的-l/usr/local/lib 

(4)binutils中的ld所設定的預設搜尋路徑順序,編譯binutils時指定。(可以通過「ld --verbose | grep search」來檢視) 

(5)二進位制程式的搜尋路徑順序為path環境變數中所設定。一般/usr/local/bin高於/usr/bin

(6)編譯時的標頭檔案的搜尋路徑順序,與library的查詢順序類似。一般/usr/local/include高於/usr/include

大家注意編譯時查詢的路徑可以通過gcc -l引數或者library_path來指定,但是執行時的查詢路徑卻不包含gcc -l和library_path環境變數指定的路徑,所以這樣就會出現我們剛開始所說的那個問題,編譯時通過-l指定了動態庫的搜尋路徑,編譯也通過了,但是執行時卻會報錯,這是因為執行時查詢動態庫的路徑還沒指定,所以我們自己寫的動態庫就找不到了,而要解決這個問題,通過設定環境變數ld_library_path或者修改/etc/ld.so.conf(記得修改完了執行ldconfi來生成ld.so.cache)就可以了。如下圖所示:

Linux動態庫的查詢路徑

前兩天寫了乙個動態庫,然後試圖編譯到程式裡面去執行,結果發現編譯的時候通過gcc的 l引數來指定路徑僅僅能讓編譯通過,執行時還是會出問題的。比如下面這個例子 main.c是主程式,sum.c中間含有乙個函式add,用來執行加法,如下 1 2 main.c3 4 include 5 6int add ...

Linux動態庫的查詢路徑

上頭需要把專案從windows系統移動到linux下,作為對linux半吊子的我卻無意承擔了這個工作,從此填坑深如海。原專案實在msvc qt開發的,還好qt是跨平台的,但是windows和linux的執行還是有所差距的。以下記錄linux下動態庫的搜尋路徑,多數內容來自csdn中的其他大神。這個過...

GNU GCC查詢路徑

1.標頭檔案 gcc 在編譯時如何去尋找所需要的標頭檔案 header file的搜尋會從 i開始 然後找gcc的環境變數 c include path,cplus include path,objc include path 再找內定目錄 usr include usr local include...