1. 搜尋路徑
- 1.1 連結時搜尋路徑
,-L path
,-rpath-link
LD_LIBRARY_PATH
- 1.2 運作時搜尋路徑
,-Wl
,-rpath path
運作搜尋路徑優先級:LD_LIBRARY_PATH
- 可執行程式的RUNPATH段
- 可執行程式的RPATH段
- LD_LIBRARY_PATH
- /etc/ld.so.cache
- /usr/lib/、/lib/
1.3 使用 ldd 指令找不到對應的共享庫檔案
- 可能是兩種情況引起的:
- 共享庫沒有安裝在該系統中;
- 共享庫儲存在 /etc/ld.so.conf 檔案列出的搜尋路徑之外的位置;
目錄下的相應位置, 如:/usr/local
或/usr/local/bin
, 以便與系統自身的程式或函數庫相差別; 而許多 Linux 系統的/usr/local/lib
檔案中預設又不包含/etc/ld.so.conf
。是以,往往會出現已經安裝了共享庫,但是卻無法找到共享庫的情況。/usr/local/lib
-
具體解決辦法如下:
檢查 /etc/ld.so.conf 檔案,如果其中缺少 /usr/local/lib 目錄,就添加進去;
!!! 注意 !!!: 在修改了
檔案或者在系統中安裝了新的函數庫之後,需要運作/etc/ld.so.conf
指令 ,該指令用來重新整理系統的共享庫緩存(為了減少共享庫系統的庫搜尋時間,共享庫系統維護了一個共享庫 soname 的緩存檔案ldconfig
)。/etc/ld.so.cache
2. 版本相容和soname機制
2.1 建立so:
% gcc –shared –Wl,-soname,libname.so.x –o libname.x.y.z x.o
可以在編譯動态庫的同時給動态庫建立soname
(libname.so.x)
,
libname.x.y.z
是動态庫的realname,其中:
- x表示主版本号,在改變庫裡的任何函數接口時才進行改變,接口變以後,前面用到這個函數的程式就不能運作了,
- y表示次版本号,是不改變任何函數的接口,隻加了幾個新的函數,這樣前面的程式也能運作,
- z表示維護号,是修改現有函數的bug時才改變。
如果你沒有改大版本号,這時隻需要把新動态庫庫覆寫掉舊動态庫就行了;
但如果大版本号改了,那新舊動态庫要同時存在,新程式需要新soname,舊程式需要舊soname。
2.2 連結so:
% gcc test.c –lname –L .
-L . 指定linkname
(libname.so)
所在的目錄,它是到實際的庫檔案的一個軟連結,
libname.x.y.z
檔案中會有soname的資訊
(libname.x)
, ld把soname的資訊儲存在生成的可執行代碼中; 連結時一般是連結到最新的庫檔案,但不需要知道具體的版本号。
2.3 運作時加載:
程式執行的時候就會加載
soname(libname.x)
–>
realname(libname.x.a.b)
并運作。
2.4 相關檔案彙總
#lib 目錄中每個庫檔案一般會有以下幾個相關檔案
#連結的時候用,把實際檔案的soname資訊包含到可執行檔案中
lrwxrwxrwx root root -- : libname.so -> libname.so..
#運作的時候用,根據可執行檔案中的soname資訊查找實際的庫檔案
lrwxrwxrwx root root -- : libname.so. -> libname.so..
#實際的庫檔案
-rwxr-xr-x root root -- : libname.so..
3. 一些實用的小技巧
隻要在gcc上指定連接配接庫的名字,ld預設就會把它連接配接到目标程式中去,然而一些無意義的動态庫連結到可執行程式隻會使程式的啟動速度變慢:
- 使用ldd -u xxx檢視xxx中不需要連結的so
- 使用-Wl,–as-needed編譯選項讓編譯器來決定連結哪些必要的so(注意-Wl,和後面選項之間不能有空格)
參見:http://blog.chinaunix.net/uid-27105712-id-3313293.html