![Linux靜態(tài)庫與共享庫基礎(chǔ)筆記_第1頁](http://file4.renrendoc.com/view/bb590fffac4d747b5411ea39618a9710/bb590fffac4d747b5411ea39618a97101.gif)
![Linux靜態(tài)庫與共享庫基礎(chǔ)筆記_第2頁](http://file4.renrendoc.com/view/bb590fffac4d747b5411ea39618a9710/bb590fffac4d747b5411ea39618a97102.gif)
![Linux靜態(tài)庫與共享庫基礎(chǔ)筆記_第3頁](http://file4.renrendoc.com/view/bb590fffac4d747b5411ea39618a9710/bb590fffac4d747b5411ea39618a97103.gif)
![Linux靜態(tài)庫與共享庫基礎(chǔ)筆記_第4頁](http://file4.renrendoc.com/view/bb590fffac4d747b5411ea39618a9710/bb590fffac4d747b5411ea39618a97104.gif)
![Linux靜態(tài)庫與共享庫基礎(chǔ)筆記_第5頁](http://file4.renrendoc.com/view/bb590fffac4d747b5411ea39618a9710/bb590fffac4d747b5411ea39618a97105.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
WordLinux靜態(tài)庫與共享庫基礎(chǔ)筆記1、目標(biāo)庫
編譯程序的一種簡單方式是簡單地將每一個(gè)源文件編譯成目標(biāo)文件,然后將這些目標(biāo)鏈接在一起組成可執(zhí)行程序:
gcc-gprog.cmod1.cmod2.cmod3.cgcc-gprog_nolibprog.omod1.omod2.omod3.o
鏈接實(shí)際上是用鏈接器ld來完成的,使用gcc命令鏈接一個(gè)程序時(shí),編譯器會(huì)再幕后調(diào)用ld。
為了解決共享的問題,可以將一組目標(biāo)文件組織成一個(gè)對象庫,對象庫分為兩種:
靜態(tài)庫
共享庫,比靜態(tài)庫更具優(yōu)勢
2、靜態(tài)庫
靜態(tài)庫也稱為歸檔文件,有點(diǎn):
可以將一組經(jīng)常被調(diào)用到的目標(biāo)文件組織成單個(gè)庫文件,這樣避免構(gòu)建多個(gè)程序時(shí)反復(fù)編譯原來代碼的問題
鏈接命令變得更加簡單,鏈接時(shí)只需要指定靜態(tài)庫的名稱即可,不需要列出一個(gè)個(gè)目標(biāo)文件
2.1、創(chuàng)建和維護(hù)靜態(tài)庫
使用ar命令能夠創(chuàng)建和維護(hù)靜態(tài)庫,靜態(tài)庫的名稱一般為libname.a:
arop(ti)onsarchiveobject-filr...
options參數(shù)由一系列的字母構(gòu)成,其中一個(gè)是操作碼,其他是可能影響操作的執(zhí)行修飾符:
r:替換,將一個(gè)目標(biāo)文件插入到歸檔文件中并取代同名的目標(biāo)文件
t:目錄表,顯示歸檔中的目錄表,默認(rèn)情況下只會(huì)列出歸檔文件中目標(biāo)文件的名稱,添加v修飾之后可以看到記錄在歸檔文件中的各個(gè)目標(biāo)文件的其他特性
d:從歸檔文件中刪除一個(gè)模塊
2.2、使用靜態(tài)庫
程序和靜態(tài)庫鏈接起來存在的兩種方式:
在連接命令中指定靜態(tài)庫的名稱
gcc-g-cprog.cgcc-g-oprogprog.olibdemo.a
或者將靜態(tài)庫放在鏈接器搜索的其中一個(gè)標(biāo)準(zhǔn)目錄中,例如/usr/lib,然后使用-l選項(xiàng)指定庫名,庫名需要去除lib
前綴和.a后綴:
gcc-g-oprogprog.o-ldemo
如果庫不在鏈接器的搜索目錄中,則需要使用-L指定額外的目錄:
gcc-g-oprogprog.o-Llibdir-ldemo
3、共享庫概述
多個(gè)程序使用同一個(gè)靜態(tài)庫時(shí),每個(gè)程序都有自己的目標(biāo)模塊的副本,這種代碼冗余存在的缺點(diǎn):
存儲同一個(gè)目標(biāo)模塊的多個(gè)副本會(huì)浪費(fèi)磁盤空間,并且所浪費(fèi)的空間是比較大的
如果使用了同一模塊的程序在同一時(shí)刻執(zhí)行,每個(gè)程序都有自己獨(dú)立的虛擬地址空間,其中保存了一份目標(biāo)代碼副本,這將會(huì)提供系統(tǒng)中虛擬內(nèi)存的整體使用量
如果需要修改一個(gè)靜態(tài)庫的一個(gè)目標(biāo)模塊,那么所有使用這個(gè)模塊的可執(zhí)行程序都必須重新進(jìn)行鏈接合并這個(gè)變更
共享庫就是為了克服靜態(tài)庫的諸多缺點(diǎn),它還具有的優(yōu)勢有:
由于整個(gè)程序的大小變得更小了,一些情況下,程序可以完全被加載到內(nèi)存中,從而能夠更快的啟動(dòng)程序,這一點(diǎn)只有在大型共享庫正被其他程序使用時(shí)才成立,第一個(gè)加載共享庫的程序?qū)嶋H上會(huì)在啟動(dòng)時(shí)花費(fèi)更長的時(shí)間,因?yàn)楸仨氁日业焦蚕韼觳⑵浼虞d到內(nèi)存中
目標(biāo)模塊修改是,不需要重新編譯程序就可以看到變更,甚至當(dāng)運(yùn)行著的程序正在使用共享庫的現(xiàn)有版本時(shí)也能夠進(jìn)行這樣的變更
共享庫的額外開銷:
創(chuàng)建共享庫和構(gòu)建使用共享庫的程序比靜態(tài)庫更復(fù)雜
共享庫在編譯時(shí)需要使用位置獨(dú)立代碼,這在大多數(shù)架構(gòu)上會(huì)帶來性能開銷,因?yàn)樗枰褂靡粋€(gè)額外的(寄存器)
在運(yùn)行時(shí)必須要執(zhí)行符號重定位,符號重定位期間,需要對共享庫中的每個(gè)符號(變量或函數(shù))的引用修改成符合在虛擬內(nèi)存中的實(shí)際運(yùn)行時(shí)位置,這個(gè)重定位的過程需要花費(fèi)一定的時(shí)間
雖然共享庫的代碼是多個(gè)進(jìn)程共享的,但是其中的變量不是,每個(gè)使用庫的進(jìn)程會(huì)擁有自己的在庫中定義的全局和靜態(tài)變量的副本。
3.1、創(chuàng)建和使用共享庫
創(chuàng)建一個(gè)共享庫
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-sharedlibfoo.somod1.omod2.omod3.o
貢獻(xiàn)庫的命名方式一般為libname.so
可以向之前構(gòu)建的共享庫中添加單個(gè)目標(biāo)模塊,也可以從中刪除單個(gè)目標(biāo)模塊
也可以將編譯共享庫的命令放在一行:
gcc-g-fPIC-Wallmod1.cmod2.cmod3.c-shared-olibfoo.so
位置獨(dú)立的代碼
-fPIC
選項(xiàng)指定編譯器應(yīng)該生成位置無關(guān)代碼,這會(huì)改變編譯器生成執(zhí)行文件特定操作的代碼方式,包括訪問全局、靜態(tài)和外部變量,訪問字符串常量,以及獲取函數(shù)的地址,這些改變使得代碼可以在運(yùn)行時(shí)放在任意虛擬地址處,這一點(diǎn)對于共享庫來說是必須的,因?yàn)殒溄拥臅r(shí)候是無法知道共享庫代碼位于內(nèi)存何處。
在(linux)/x86-32上,可以使用不加-fPIC選項(xiàng)編譯的模塊來創(chuàng)建共享庫,為了確定一個(gè)既有目標(biāo)文件在編譯時(shí)是否使用了-fPIC選項(xiàng),可以使用檢查目標(biāo)文件符號表中是否存在_GLOBAL_OFFSET_TABLE:
nmmod1.o|grep_GLOBAL_OFFSET_TABLEre(ad)elf-smod1.o|grep_GLOBAL_OFFSET_TABLE
下面的命令中如果產(chǎn)生了輸出,則說明指定的共享庫中至少存在一個(gè)目標(biāo)模塊在編譯時(shí)沒有指定-fPIC:
objdump--all-heade(rs)libfoo.so|grep(TE)XTRELobjdump--all-headerslibfoo.so|grepTEXTREL
TEXTREL表示存在一個(gè)目標(biāo)模塊,其文本段中包含需要運(yùn)行時(shí)重定位的引用。
使用一個(gè)共享庫
為了使用共享庫需要做兩件事情,而使用靜態(tài)庫則無需完成這兩件事情:
可執(zhí)行文件中不包含它所需要的目標(biāo)文件的副本,因此需要通過某種機(jī)制找到運(yùn)行時(shí)所需要的共享庫:鏈接階段將共享庫名稱嵌入可執(zhí)行文件中,一個(gè)程序所依賴的所有共享庫列表稱為程序的動(dòng)態(tài)依賴表
在程序運(yùn)行時(shí)需要某種機(jī)制解析嵌入的庫名,即找出與在可執(zhí)行文件中指定的名稱對應(yīng)的共享庫文件,如果庫不再內(nèi)存中的話就將庫加載進(jìn)內(nèi)存
運(yùn)行時(shí)解析內(nèi)嵌庫名的工作由動(dòng)態(tài)鏈接器(也稱為動(dòng)態(tài)鏈接加載器或運(yùn)行時(shí)加載器)來完成,動(dòng)態(tài)鏈接器本身也是一個(gè)共享庫,其名稱為lib/ld-linux.so.2,所有使用共享庫的ELF可執(zhí)行文件都會(huì)用到這個(gè)共享庫。
lib/ld-linux.so.2通常是指向動(dòng)態(tài)鏈接器可執(zhí)行文件的符號鏈接,這個(gè)文件的名稱為ld-version.so。
動(dòng)態(tài)鏈接器會(huì)檢查程序所需的共享庫清單并使用一組預(yù)先定義好的規(guī)則來在文件系統(tǒng)上找出相關(guān)的庫文件。其中一些規(guī)則指定了一組存放共享庫的標(biāo)準(zhǔn)目錄,如/lib,/usr/lib。
LD_LIBRARY_PATH環(huán)境變量
通知?jiǎng)討B(tài)鏈接器一個(gè)共享庫位于一個(gè)非標(biāo)準(zhǔn)目錄中的一種方法是將該目錄添加到LD_LIBRARY_PATH
環(huán)境變量中以分號分隔的目錄列表中,如果定義了LD_LIBRARY_PATH,那么動(dòng)態(tài)鏈接器在查找標(biāo)準(zhǔn)庫目錄前會(huì)先查找該環(huán)境變量列出的目錄中的共享庫。
LD_LIBRARY_PATH=../prog#告知?jiǎng)討B(tài)鏈接器在當(dāng)前工作目錄中搜索共享庫
靜態(tài)鏈接和動(dòng)態(tài)鏈接的比較
術(shù)語鏈接通常指的是使用鏈接器ld將一個(gè)或多個(gè)編譯過的目標(biāo)文件合成一個(gè)可執(zhí)行程序,也稱為靜態(tài)鏈接。
在運(yùn)行時(shí)使用共享庫的可執(zhí)行程序需要經(jīng)歷額外的動(dòng)態(tài)鏈接階段。
3.2、共享庫soname
嵌入到可執(zhí)行程序以及動(dòng)態(tài)鏈接器在運(yùn)行時(shí)搜索的名稱除了使用真實(shí)名稱,還經(jīng)常使用別名來創(chuàng)建共享庫,這種別名稱為soname,ELF中的
DT_SONAME
標(biāo)簽。
如果共享庫擁有一個(gè)soname,那么在靜態(tài)鏈接階段會(huì)將soname嵌入到可執(zhí)行文件中,而不會(huì)使用真實(shí)名稱,同時(shí)后面的動(dòng)態(tài)鏈接器在運(yùn)行時(shí)也會(huì)使用這個(gè)soname來搜索庫,引入soname的目的是為了提供一個(gè)間接層,使得可執(zhí)行程序能夠在運(yùn)行時(shí)使用與鏈接時(shí)使用不同的但兼容的共享庫。
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-shared-Wl,-soname,libbar.so-olibfoo.somod1.omod2.omod3.o
-Wl,-soname,libbar.so等選項(xiàng)都是傳給鏈接器的指令,以將共享庫libfoo.so的soname設(shè)置為libbar.so
使用一下命令中的任意一個(gè),可以確定既有共享庫的soname:
objdump-plibz.so|grepSONAMESONAME
libz.so.1
readelf-dlibz.so|grepSONAME0x000000000000000e(SONAME)
Librarysoname:[libz.so.1]
使用soname
創(chuàng)建程序:
gcc-g-Wall-oprogprog.clibfoo.so
鏈接器檢查到庫libfoo.so包含了soname:libbar.so,就將這個(gè)soname嵌入到可執(zhí)行文件中。
使用共享庫時(shí)必須要?jiǎng)?chuàng)建一個(gè)符號鏈接,將soname指向庫的真實(shí)名稱,并且必須要將這個(gè)符號鏈接放在動(dòng)態(tài)鏈接器搜索的其中一個(gè)目錄中。
程序載入內(nèi)存以設(shè)備執(zhí)行時(shí)發(fā)生的事情:
要找出一個(gè)進(jìn)程當(dāng)前使用的共享庫則可以列出相應(yīng)的Linux特有的/proc/(PI)D/maps文件中的內(nèi)容。
4、使用共享庫的有用工具
ldd
ldd
:列出動(dòng)態(tài)依賴,顯示一個(gè)程序運(yùn)行時(shí)所需要的共享庫。
ldd
會(huì)解析出每個(gè)庫引用,使用的搜索方式與動(dòng)態(tài)鏈接器一樣,并以下面的形式顯示結(jié)果:
library-name=>resolves-to-path
對于多數(shù)的ELF文件,ldd至少會(huì)列出與ld-linux.so.2、動(dòng)態(tài)鏈接器以及標(biāo)準(zhǔn)C庫lib.so.6相關(guān)的條目。
objdump和readelf
objdump
:用來從可執(zhí)行文件、編譯過的目標(biāo)、以及共享庫中獲取各類信息,包括反(匯編)的二進(jìn)制機(jī)器碼,還可以用來顯示這些文件各個(gè)ELF節(jié)的頭部信息,當(dāng)這樣使用時(shí),它就類似于readelf,readelf能顯示類似的信息,但是格式不同。
nm
nm命令會(huì)列出目標(biāo)庫或可執(zhí)行文件中定義的一組符號,常用來尋找哪些庫定義了一個(gè)符號。
5、共享庫版本和命名規(guī)則
命名形式:
libname.somajor-id.minor-id
major-id:主要版本標(biāo)識符,區(qū)分兩個(gè)不兼容的版本
minor-id:次要版本可以是任意字符串,但是通常的形式是兩個(gè)由點(diǎn)分隔的數(shù)字,第一個(gè)數(shù)字表示次要版本,第二個(gè)數(shù)字表示該次要版本的補(bǔ)丁號或者修訂號
libdemo.so.1.0.1libdemo.so.1.0.2libdemo.so.2.0.0
共享庫的soname包括相應(yīng)的主版本標(biāo)識符,但是不包含次要版本標(biāo)識符,因此
soname的命名形式為:
libname.so.major-id
通常,會(huì)將soname
創(chuàng)建為包含真實(shí)名稱的目錄的一個(gè)相對符號鏈接:
libdemo.so.1
->libdemo.so.1.0.2libdemo.so.2
->libdemo.so.2.0.0
共享庫的一個(gè)主要版本可能有多個(gè)不同的次要版本,通常每個(gè)庫的主要版本的
soname
會(huì)指向主要版本中(最新)的次要版本,由于靜態(tài)鏈接階段會(huì)將soname
的副本(獨(dú)立于次要版本)嵌入到可執(zhí)行文件中,并且soname符號鏈接后面可能會(huì)被修改為指向更新的次要版本,從而確保在執(zhí)行期間能夠加載庫的最新的次要版本。
同一個(gè)庫的不同主要版本也能夠同時(shí)存在,被需要它們的程序分別訪問。
除了真實(shí)名稱和soname之外,通常還會(huì)為每個(gè)共享庫定義第三個(gè)名稱:鏈接器名稱,將可執(zhí)行文件與共享庫鏈接起來時(shí)會(huì)使用這個(gè)名稱,鏈接器名稱是一個(gè)只包含庫名稱不包含主要版本和次要版本標(biāo)識符的符號鏈接,其形式為libname.so,有了鏈接器名稱之后就可以構(gòu)建能夠自動(dòng)使用共享庫(最新版)本的鏈接命令。
鏈接器名稱一般與它所引用的文件位于同一個(gè)目錄中,它既可以鏈接到真實(shí)名稱,也可以鏈接到庫的最新主要版本的soname。通常最好使用指向soname
的鏈接,從而對soname的修改會(huì)自動(dòng)反應(yīng)到鏈接器名稱。
如果需要使用一個(gè)舊版本的共享庫,就不能使用鏈接器名稱,要使用真實(shí)名稱或者soname來指示出需要的版本。
5.1、使用標(biāo)準(zhǔn)規(guī)范創(chuàng)建一個(gè)共享庫
創(chuàng)建目標(biāo)文件
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.c
創(chuàng)建共享庫,指定真實(shí)名稱和soname
gcc-g-shared-Wl,-soname,libdemo.so.1-olibdemo.so.1.0.1mod1.omod2.omod3.o
為soname和鏈接器名稱創(chuàng)建恰當(dāng)?shù)姆栨溄?/p>
ln-slibdemo.so.1.0.1libdemo.so.1ln-slibdemo.so.1libdemo.so
使用鏈接器名稱構(gòu)建可執(zhí)行文件
gcc-g-Wall-oprogprog.c-L.-ldemoLD_LIBRARY_PATH=../prog
5.2、安裝共享庫
共享庫及其關(guān)聯(lián)的符號鏈接一般會(huì)被安裝到一個(gè)標(biāo)準(zhǔn)目錄中,標(biāo)準(zhǔn)目錄包括:
/usr/lib:是大多數(shù)標(biāo)準(zhǔn)庫安裝的目錄
/lib:應(yīng)該將系統(tǒng)啟動(dòng)時(shí)用到的庫安裝到這個(gè)目錄,因?yàn)橄到y(tǒng)啟動(dòng)時(shí)可能還沒有掛載/usr/lib
/usr/local/lib:應(yīng)該將非標(biāo)準(zhǔn)或者實(shí)驗(yàn)性質(zhì)的庫安裝到這個(gè)目錄
/etc/ld.so.conf中列出的目錄
安裝完成后一般需要?jiǎng)?chuàng)建soname
和鏈接器名稱的符號鏈接:
mvlibdemo.so.1.0.1/usr/libcd/usr/libln-slibdemo.so.1.0.1libdemo.so.1#創(chuàng)建sonameln-slibdemo.so.1libdemo.so#創(chuàng)建鏈接器名稱
ldconfig
ldconfig解決了共享庫的兩個(gè)潛在問題:
共享庫可以位于各種目錄中,如果動(dòng)態(tài)鏈接器需要通過搜索這些目錄來找一個(gè)庫并加載這個(gè)庫,整個(gè)過程將非常慢
當(dāng)安裝了新版本的庫或者刪除了舊版本的庫,那么
soname符號鏈接就不是最新的
ldconfig可以通過執(zhí)行兩個(gè)任務(wù)來解決這些問題:
它搜索一組標(biāo)準(zhǔn)的目錄并創(chuàng)建或更新一個(gè)緩存文件/etc/ld.so.cache使之包含在所有這些目錄中的主要版本(每個(gè)庫的主要版本的最新的次要版本)列表,動(dòng)態(tài)鏈接器在運(yùn)行時(shí)解析庫名稱時(shí)會(huì)輪流使用這個(gè)緩存文件:
為了構(gòu)建這個(gè)緩存,ldconfig會(huì)搜索在/etc/ld.so.conf中指定的目錄,然后搜索/lib和/usr/lib
`/etc/ld.so.conf文件由一個(gè)目錄路徑名(應(yīng)該是絕對路徑名)列表構(gòu)成,其中路徑名之間用換行、空格、制表符、逗號或冒號分隔
在一些發(fā)行版中,/usr/local/lib目錄也位于這個(gè)列表中
ldconfig-p會(huì)顯示/etc/ls.so.cache的當(dāng)前內(nèi)容
它檢查每個(gè)庫的各個(gè)主要版本的最新次要版本以找出嵌入的soname,然后在同一目錄中為每個(gè)soname創(chuàng)建(或更新)相對符號鏈接:
為了能夠正確執(zhí)行這些動(dòng)作,ldconfig要求庫的名稱要根據(jù)前面介紹的規(guī)范來命名:庫的真實(shí)名稱包含主要和次要標(biāo)識符,它們隨著庫的版本的更新而恰當(dāng)?shù)脑鲩L
可以使用命令行選項(xiàng)來指定它執(zhí)行其中一個(gè)動(dòng)作:-N選項(xiàng)會(huì)防止緩存的重建,-X選項(xiàng)會(huì)阻止soname符號鏈接的創(chuàng)建。此外,-v(verbose)選項(xiàng)會(huì)使得ldconfig輸出描述其所執(zhí)行的動(dòng)作的信息
每當(dāng)安裝了一個(gè)新的庫,更新或者刪除一個(gè)既有庫,以及/etc/ld.so.conf中的目錄列表被修改后,都運(yùn)行相應(yīng)的ldconfig。
安裝一個(gè)庫的兩個(gè)不同主要版本:
mvlibdemo.so.1.0.1libdemo.so.2.0.0/usr/lib
為鏈接器名稱創(chuàng)建符號鏈接:
ln-slibdemo.so.2libdemo.so
如果更新庫的一個(gè)次要版本,由于鏈接器名稱指向了最新的soname,因此ldconfig還能取得保持鏈接器名稱的最新效果:
mvlibdemo.so.2.0.1/usr/lib
如果使用的是私有庫,即沒有安裝在上述的標(biāo)準(zhǔn)目錄中的庫,那么可以使用-n選項(xiàng)讓ldconfig創(chuàng)建soname,這個(gè)選項(xiàng)指定了只處理在命令行中列出的目錄的庫,無需更新緩存文件。
使用ldconfig來處理當(dāng)前工作目錄中的庫:
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-c-shared-Wl,-soname,libdemo.so.1-olibdemo.so.1.0.1mod1.omod2.omod3.o/sbin/ldconfig-nv.
5.3、兼容與不兼容庫比較
滿足下列條件時(shí)表示修改過的庫與既有版本兼容:
庫中所有公共方法和變量的語義保持不變
沒有刪除庫的公共API中的函數(shù)和變量,但向公共API中添加新函數(shù)和變量
每個(gè)函數(shù)分配的結(jié)構(gòu)以及沒和函數(shù)的返回結(jié)構(gòu)保持不變
如果這些條件都滿足,更新庫時(shí)只需要調(diào)增既有庫的次要版本號,否則就要?jiǎng)?chuàng)建新的主版本。
5.4、升級共享庫
共享庫的優(yōu)點(diǎn)之一就是當(dāng)一個(gè)運(yùn)行著的程序正在使用共享庫的一個(gè)既有版本時(shí),也能夠安裝新的主要版本或者次要版本的庫,需要做的是:
創(chuàng)建新的庫版本,將其安裝到恰當(dāng)?shù)哪夸?/p>
根據(jù)需要更新soname和鏈接器名稱符號鏈接,或者使用ldconfig完成這部分工作
更新次要版本:
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-c-shared-Wl,-soname,libdemo.so.1-olibdemo.so.1.0.2mod1.omod2.omod3.omvlibdemo.so.1.0.2/usr/libldconfig-v|greplibdemo
更新主要版本:
gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-c-shared-Wl,-soname,libdemo.so.2-olibdemo.so.2.0.0mod1.omod2.omod3.omvlibdemo.so.2.0.0/usr/libldconfig-v|greplibdemocd/usr/libln-sflibdemo.so.2libdemo.so
6、在目標(biāo)文件中指定庫搜索目錄
通知?jiǎng)討B(tài)鏈接器共享庫的位置的方式:
LD_LIBRARY_PATH環(huán)境變量中指定
將共享庫安裝到標(biāo)準(zhǔn)庫目錄:/lib,/usr/lib,/etc/ls.so.conf中列出的其中一個(gè)目錄
第三種方式:在靜態(tài)編輯階段可以在執(zhí)行文件中插入一個(gè)在運(yùn)行時(shí)搜索共享庫的目錄列表,這種方式對于庫位于一個(gè)固定的但不屬于動(dòng)態(tài)鏈接器搜索標(biāo)準(zhǔn)位置時(shí)非常有用,在創(chuàng)建文件時(shí)需要增加-rpath鏈接器選項(xiàng)。
gcc-g-Wall,-rpath,/home/mtk/pdir-oprogprog.clibdemo.so
將字符串/home/mtk/pdir復(fù)制到可執(zhí)行文件prog的運(yùn)行時(shí)庫路徑列表中,在程序運(yùn)行時(shí),動(dòng)態(tài)鏈接器在解析共享庫引用時(shí)還會(huì)搜索這個(gè)路徑。
指定多個(gè)目錄:
多次指定-rpath選項(xiàng),所有這些列出的目錄會(huì)被鏈接成一個(gè)放到可執(zhí)行文件中的有序-rpath
列表
在一個(gè)-rpath選項(xiàng)中可以指定多個(gè)由分號分隔開的目錄列表,運(yùn)行時(shí),動(dòng)態(tài)鏈接器會(huì)按照-rpath選項(xiàng)中指定的目錄順序來搜索目錄
-rpath的一個(gè)可替代方案就是使用LD_RUN_PARH環(huán)境變量,可以將由一個(gè)逗號分隔開的目錄的字符串賦值給該變量,只有當(dāng)構(gòu)建可執(zhí)行文件時(shí)沒有指定-rpath選項(xiàng)才會(huì)使用LD_RUN_PATH
6.1、在構(gòu)建貢獻(xiàn)庫時(shí)使用-rpath鏈接器選項(xiàng)
假設(shè)有一個(gè)庫lib1.so依賴于另一個(gè)共享庫lib2.so,另外再假設(shè)這些庫分別位于非標(biāo)準(zhǔn)目錄d1和d2中:
首先在pdir/d2目錄中構(gòu)建libx2.so,這里省略了庫的版本號和soanme:
cd/home/mtk/pdir/d2gcc-g-c-fPIC-Wallmodx2.cgcc-g-shared-olibx2.somodx2.o
接著在pdir/d1目錄中構(gòu)建libx1.so。由于libx1.so依賴于lib2.so,并且libx2.so位于一個(gè)非標(biāo)準(zhǔn)目錄中,因此在指定libx2.so的運(yùn)行時(shí)位置時(shí)需要使用-rpath鏈接器選項(xiàng)。這個(gè)選項(xiàng)的取值與庫的鏈接時(shí)位置可以不同:
cd/home/mtk/pdir/d1gcc-g-c-Wallmodx1.cgcc-g-shared-olibx1.somodx1.o-Wl,-rpath,/home/mtk/pdir/d2-L/home/mtk/pdir/d2-lx2
pdir目錄中構(gòu)建主程序,由于主程序使用了
libx1.so并且這個(gè)庫位于一個(gè)非標(biāo)準(zhǔn)目錄中,因此還需要使用-rpath鏈接器選項(xiàng):
cd/home/mtk/pdirgcc-g-Wall-oprogprog.c-Wl,-rpath,/home/mtk/pdir/d1-L/home/mtk/pdir/d1-lx1
在鏈接主程序是,無需指定libx2.so,由于鏈接器能夠分析libx1.so中的rpath列表,因此它能夠找到libx2.so,同時(shí)在靜態(tài)鏈接階段解析出所有的符號。
可以通過readelf--dynamic或者等價(jià)的readelf-d命令的輸出來查看rpath列表。
6.2、ELFDT_RPATH和DT_RUNPATH條目
第一版ELF規(guī)范中,只有一種rpath列表能夠被嵌入到可執(zhí)行文件或共享庫中,對應(yīng)
ELF
文件中的DT_RPATH標(biāo)簽。后續(xù)的ELF舍棄了DT_RPATH,同時(shí)引入DT_RUNPATH來表示rpath列表,兩者的差別在于動(dòng)態(tài)鏈接器在運(yùn)行時(shí)搜索共享庫時(shí)它們相對于LD_LIBRARY_PATH環(huán)境變量的優(yōu)先級,DT_RPATH的優(yōu)先級更高,DT_RUNPATH的優(yōu)先級更低。
默認(rèn)情況下,鏈接器將rpath列表創(chuàng)建為DT_RPATH標(biāo)簽。為了讓鏈接器將rpath列表創(chuàng)建為DT_RUNPATH條目必須使用--enable-new-dtags。
6.3、在rpath中使用$ORIGIN
應(yīng)用程序中使用了自身的共享庫,但同時(shí)不希望強(qiáng)制要求將這些庫安裝在其中一個(gè)標(biāo)準(zhǔn)目錄中,可以在構(gòu)建鏈接器的時(shí)候,增加$ORIGIN,動(dòng)態(tài)鏈接器將這個(gè)字符串解釋成"包含應(yīng)用程序的目錄":
gcc-Wl,-rpath,'ORIGIN'/lib...
7、在運(yùn)行時(shí)找出共享庫
在解析庫依賴時(shí),動(dòng)態(tài)鏈接器首先會(huì)檢查各個(gè)依賴字符串以確定它是否包含/,如果找到了一個(gè)斜線,那么依賴字符串就會(huì)被解釋成一個(gè)路徑名,并且會(huì)使用該路徑名加載庫,否則動(dòng)態(tài)鏈接器會(huì)使用下面的規(guī)則來搜索共享庫:
如果可執(zhí)行文件的DT_RPATH運(yùn)行時(shí)庫路徑列表中包含目錄并且不包含DT_RUNP
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 上漿黃麻紗行業(yè)行業(yè)發(fā)展趨勢及投資戰(zhàn)略研究分析報(bào)告
- 沖壓模具開發(fā)合同范本
- 人工挖方合同范本
- 關(guān)于安裝監(jiān)控合同范本
- 代銷合同范例5篇
- 養(yǎng)殖基地養(yǎng)雞合同范本
- 無合同勞動(dòng)仲裁申請書范本
- 企業(yè)房產(chǎn)贈(zèng)與合同范本
- 借錢協(xié)議合同范本
- 公司電費(fèi)簡易合同范本
- 2025年電力鐵塔市場分析現(xiàn)狀
- 臨床提高膿毒性休克患者1h集束化措施落實(shí)率PDCA品管圈
- DB53∕T 1269-2024 改性磷石膏用于礦山廢棄地生態(tài)修復(fù)回填技術(shù)規(guī)范
- JBT 14727-2023 滾動(dòng)軸承 零件黑色氧化處理 技術(shù)規(guī)范 (正式版)
- GB/T 3478.1-1995圓柱直齒漸開線花鍵模數(shù)基本齒廓公差
- GB/T 1346-2001水泥標(biāo)準(zhǔn)稠度用水量、凝結(jié)時(shí)間、安定性檢驗(yàn)方法
- FZ/T 25001-2012工業(yè)用毛氈
- 中國工運(yùn)史知識競答附答案
- 瑞幸咖啡SWOT分析
- DL∕T 1867-2018 電力需求響應(yīng)信息交換規(guī)范
- 小學(xué)生品德發(fā)展水平指標(biāo)評價(jià)體系(小學(xué))
評論
0/150
提交評論