linux中動態(tài)鏈接庫的搜索順序
//
// by kirk,2008.11.21,文中有bug請搞緊與我聯(lián)系:-)
//
在接手一個(gè)很古老的程序時(shí),發(fā)現(xiàn)其所使用的動態(tài)庫都實(shí)在是太陳舊了,正式運(yùn)行環(huán)境中部署的庫都是相適應(yīng)的,而目前的開發(fā)測試環(huán)境中均是部署的新的升級版本。為了能在這些環(huán)境下開發(fā)測試,程序得能在自定義的路徑里來搜索。因此在這里復(fù)習(xí)一下linux中程序?qū)討B(tài)鏈接庫的搜索順序,如下所述:
1.首先查看程序文件的.dynamic 段是否包含了一個(gè)叫DT_RPATH的項(xiàng)(它是一個(gè)以冒號分隔的庫文件搜索目錄列表)。
怎么設(shè)置這個(gè)選項(xiàng)?
需要在編譯連接程序的時(shí)候使用-Wl,-rpath選項(xiàng),假設(shè)一個(gè)程序test需要使用liblib.so庫,如下所示進(jìn)行編譯連接:
g++ -o test -L. -llib -Wl,rpath=./ test.cpp
這樣在執(zhí)行test程序時(shí),test便會先到./即當(dāng)前目錄下查找所需要的動態(tài)庫liblib.so
2.查找是否存在環(huán)境變量 LD_LIBRARY_PATH(它是一個(gè)以冒號分隔的庫文件搜索目錄列表)。
怎么設(shè)置這個(gè)選項(xiàng)?當(dāng)然是設(shè)置linux下的環(huán)境變量就可以了。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
當(dāng)然,這種方法是對當(dāng)前登錄生效的。如果想開機(jī)即有效,跟其它環(huán)境變量的設(shè)置也是一樣,需要修改一些配置文件。
3.查看庫高速緩存文件 /etc/ld.so.conf ,它包含了庫名和路徑的一個(gè)對應(yīng)列表,如果庫名存在,連接器就使用它對應(yīng)的路徑,用這個(gè)查找方法能夠找到大部分的庫。
怎么設(shè)置這個(gè)選項(xiàng)?可以直接編輯ld.so.conf加入需要查找的路徑,也可以在/etc/ld.so.conf.d目錄下的己有文件中加入路徑,或者在該目錄下新建一個(gè)文件(名字為*.conf即可),再把需要的路徑加入到該文件中。最后執(zhí)行l(wèi)dconfig即可生效。
4.查找默認(rèn)路徑/lib和/usr/lib,
如果經(jīng)過了以上的步驟仍然查找失敗,則將報(bào)錯(cuò)并退出相關(guān)程序。
對于前三個(gè)步驟來說,我們均是可以進(jìn)行設(shè)置調(diào)整的,其中第三個(gè)步驟中的設(shè)置需要root權(quán)限才能進(jìn)行,且會影響所有的程序。當(dāng)使用第一、第二中的方法進(jìn)行了設(shè)置調(diào)整后,我們便可以使多種版本的庫共存在同一環(huán)境下進(jìn)行測試,同名也無所謂。
*********************************************************************
環(huán)境變量LD_LIBRARY_PATH用來指定查找共享庫時(shí)除了默認(rèn)路徑之外的其他路徑。(該路徑在默認(rèn)路徑之前查找)
移植程序時(shí)的經(jīng)常碰到需要使用一些特定的動態(tài)庫,而這些編譯好的動態(tài)庫放在我們自己建立的目錄里,這時(shí)我們可以設(shè)置LD_LIBRARY_PATH。
例:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/work/lib/
這樣就可以使用/work/lib/下的庫文件了,運(yùn)行程序后系統(tǒng)會自動到環(huán)境變量LD_LIBRARY_PATH指定的路徑中查找其所需的庫。
系統(tǒng)查找動態(tài)庫的順序
系統(tǒng)先找LD_LIBRARY_PATH下的庫再找/lib and /usr/lib等路徑下的庫,還有/etc/ld.so.conf里指定的路徑(如果ld.so.conf存在),man ldconfig for more information
[url=http://infomax/bbs/misc.php?action=viewratings&tid=111&pid=228][/url]
使Linux啟動之后就加載LD_LIBRARY_PATH的路徑
/etc/rc.d/rc.local文件中加入export LD_LIBRARY_PATH="xxxxx" 即可
如果在鏈接時(shí)使用了"-R"和"-L"選項(xiàng),則相關(guān)動態(tài)庫的路徑將保存在ELF文件中,于
是以后的運(yùn)行中不再需要設(shè)置環(huán)境變量去定位動態(tài)庫。比如,有一個(gè)
/usr/local/lib/libfoo.so,而你的bar程序需要這個(gè)libfoo.so,編譯、鏈接時(shí)最好
這樣 :gcc -Wall -pipe -O3 -o bar -R/usr/local/lib -L/usr/local/lib bar.c -lfoo
(#man gcc ,沒發(fā)現(xiàn)-R或-rpath選項(xiàng),待查)