?? unix系統(tǒng)開發(fā)-動(dòng)態(tài)鏈接程序搜索目錄.txt
字號:
UNIX系統(tǒng)開發(fā)-動(dòng)態(tài)鏈接程序搜索目錄
在采用動(dòng)態(tài)鏈接方式對程序進(jìn)行編譯,鏈接時(shí)候。鏈接程序只是在最終的可執(zhí)行文件中記錄下關(guān)于所引用的共享庫中的符號的一些登記信息,以便在程序被執(zhí)行時(shí),動(dòng)態(tài)鏈接程序能夠根據(jù)這些登記信息找到相應(yīng)的代碼。因此登記動(dòng)態(tài)鏈接方式而言,除了在鏈接階段涉及到對庫文件的搜索路徑外,還有一個(gè)在程序運(yùn)行階段對庫文件的搜索問題。
前一個(gè)問題我們知道借助于LD_LIBRARY_PATH環(huán)境變量及cc命令行中的-L選項(xiàng)已經(jīng)得到了比較好的解決。對于第二個(gè)問題,我們必須提供一種機(jī)制,使得動(dòng)態(tài)鏈接程序能夠找到相應(yīng)的動(dòng)態(tài)庫,然后才能將其代碼映射到其自己的地址空間中。
UNIX系統(tǒng)中對這些問題的解決實(shí)際上采取了類似的方法。程序員可以使用LD_RUN_PATH來解決上面的第二個(gè)問題。同PATH變量相同,LD_RUN_PATH的值也是一系列由冒號分隔的絕對路徑名組成的。在此環(huán)境變量中,我們可以列出所用到的動(dòng)態(tài)庫所在的那些目錄,一般動(dòng)態(tài)鏈接程序在程序運(yùn)行時(shí)對這些目錄進(jìn)行搜索。例如,我們可以定義LD_RUN_PATH的值如下:
$ LD_RUN_PATH=$HOME/lib;export LD_RUN_PATH
這里我們在LD_RUN_PATH中只指定了一個(gè)目錄名。在使用如下命令:
$ cc -L $HOME/lib -o myprog myprog.c -l test
建立可執(zhí)行文件myprog之后,在shell提示符下輸入:
$ myprog ...
在執(zhí)行此程序時(shí),動(dòng)態(tài)鏈接程序?qū)⒏鶕?jù)LD_RUN_PATH中所記錄的路徑($HOME/lib),在其中依次搜索有關(guān)的動(dòng)態(tài)庫libtest.so。
在搜索完LD_RUN_PATH指定的各個(gè)目錄之后,動(dòng)態(tài)鏈接程序?qū)⒏鶕?jù)缺省設(shè)置搜索系統(tǒng)標(biāo)準(zhǔn)位置。對于動(dòng)態(tài)鏈接程序而言,庫的標(biāo)準(zhǔn)位置只有/usr/lib。編譯系統(tǒng)所提供的庫的每一個(gè)可執(zhí)行版本都保留在/usr/lib目錄中。
上一節(jié)我們介紹過的環(huán)境變量LD_LIBRARY_PATH實(shí)際上也能起到同樣的作用。并且使用此環(huán)境變量還有一個(gè)好處就是在鏈接生成了可執(zhí)行文件之后,可以把此可執(zhí)行文件用到的共享庫移至另一個(gè)目錄中,不必重新對程序進(jìn)行鏈接。只需恰當(dāng)?shù)卦O(shè)置LD_LIBRARY_PATH的值,仍然可以讓動(dòng)態(tài)鏈接程序找到相應(yīng)的動(dòng)態(tài)庫。
仍以上例來說明這個(gè)問題。假定在生成了myprog文件之后,我們將libtest.so移至另外一個(gè)目錄$HOME/sharedlib下。此時(shí)僅僅將LD_RUN_PATH的值設(shè)成是$HOME/sharedlib是不行的,因?yàn)榫幾g產(chǎn)生的可執(zhí)行程序?qū)o法使用$HOME/sharedlib目錄下的libtest.so。但可以在LD_LIBRARY_PATH中指定新的目錄。
$LD_LIBRARY_PATH= $HOME/sharedlib;export LD_LIBRARY_PATH
這樣再執(zhí)行myprog時(shí),動(dòng)態(tài)鏈接程序?qū)⑹紫仍?HOME/lib中搜索libtest.so。當(dāng)然此時(shí)它是找不到該文件的。于是根據(jù)LD_LIBRARY_PATH的值,動(dòng)態(tài)鏈接程序?qū)⑺阉?HOME/sharedlib目錄,這時(shí)它將找到所需要的庫。
此種方法能夠奏效是因?yàn)閘ibtest.so的路徑名在myprog中不是硬編碼,所以可以在執(zhí)行程序時(shí)引導(dǎo)動(dòng)態(tài)鏈接程序搜索另外一個(gè)目錄。也就是說,可以移動(dòng)共享庫而不致使引用程序無法運(yùn)行,但是如果在同動(dòng)態(tài)庫鏈接時(shí)使用的是硬編碼,那么就無法獲得此種靈活性了。
硬編碼是什么意義呢?這種做法實(shí)際上是違反cc命令行用-l指定待鏈接的庫的約定,而直接使用庫文件的全路徑名進(jìn)行鏈接。例如我們可以將myfunc.c作成一個(gè)動(dòng)態(tài)鏈接庫:
$ cc -K PIC -G -o $HOME/myfunc myfunc.c
這里生成的動(dòng)態(tài)庫的名稱是$HOME/myfunc。由于沒有遵循對動(dòng)態(tài)庫的命名約定,故我們想鏈接該庫時(shí)將不能再使用-l選項(xiàng)的方法。而只好使用如下的"硬編碼":
$ cc -o myprog myprog.c $ HOME/myfunc
使用此種方法,編譯鏈接也能夠成功,但如果其后我們將myfunc移至另外某個(gè)目錄下,則除了重新鏈接myprog之外別無他法。
動(dòng)態(tài)鏈接的動(dòng)態(tài)特點(diǎn)使得我們可以在不改變函數(shù)調(diào)用接口的前提下,對共享庫的實(shí)現(xiàn)進(jìn)行一定程度的更新,而不用重新對用到的該共享庫的程序進(jìn)行編譯、鏈接。當(dāng)然在動(dòng)態(tài)鏈接庫被更新之后,需要核實(shí)一下使用到該動(dòng)態(tài)庫的程序與新版本的兼容性,這個(gè)可以使用ldd命令來完成。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -