Linux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記_第1頁(yè)
Linux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記_第2頁(yè)
Linux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記_第3頁(yè)
Linux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記_第4頁(yè)
Linux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記_第5頁(yè)
已閱讀5頁(yè),還剩17頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

WordLinux靜態(tài)庫(kù)與共享庫(kù)基礎(chǔ)筆記1、目標(biāo)庫(kù)

編譯程序的一種簡(jiǎn)單方式是簡(jiǎn)單地將每一個(gè)源文件編譯成目標(biāo)文件,然后將這些目標(biāo)鏈接在一起組成可執(zhí)行程序:

gcc-gprog.cmod1.cmod2.cmod3.cgcc-gprog_nolibprog.omod1.omod2.omod3.o

鏈接實(shí)際上是用鏈接器ld來(lái)完成的,使用gcc命令鏈接一個(gè)程序時(shí),編譯器會(huì)再幕后調(diào)用ld。

為了解決共享的問(wèn)題,可以將一組目標(biāo)文件組織成一個(gè)對(duì)象庫(kù),對(duì)象庫(kù)分為兩種:

靜態(tài)庫(kù)

共享庫(kù),比靜態(tài)庫(kù)更具優(yōu)勢(shì)

2、靜態(tài)庫(kù)

靜態(tài)庫(kù)也稱為歸檔文件,有點(diǎn):

可以將一組經(jīng)常被調(diào)用到的目標(biāo)文件組織成單個(gè)庫(kù)文件,這樣避免構(gòu)建多個(gè)程序時(shí)反復(fù)編譯原來(lái)代碼的問(wèn)題

鏈接命令變得更加簡(jiǎn)單,鏈接時(shí)只需要指定靜態(tài)庫(kù)的名稱即可,不需要列出一個(gè)個(gè)目標(biāo)文件

2.1、創(chuàng)建和維護(hù)靜態(tài)庫(kù)

使用ar命令能夠創(chuàng)建和維護(hù)靜態(tài)庫(kù),靜態(tài)庫(kù)的名稱一般為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)庫(kù)

程序和靜態(tài)庫(kù)鏈接起來(lái)存在的兩種方式:

在連接命令中指定靜態(tài)庫(kù)的名稱

gcc-g-cprog.cgcc-g-oprogprog.olibdemo.a

或者將靜態(tài)庫(kù)放在鏈接器搜索的其中一個(gè)標(biāo)準(zhǔn)目錄中,例如/usr/lib,然后使用-l選項(xiàng)指定庫(kù)名,庫(kù)名需要去除lib

前綴和.a后綴:

gcc-g-oprogprog.o-ldemo

如果庫(kù)不在鏈接器的搜索目錄中,則需要使用-L指定額外的目錄:

gcc-g-oprogprog.o-Llibdir-ldemo

3、共享庫(kù)概述

多個(gè)程序使用同一個(gè)靜態(tài)庫(kù)時(shí),每個(gè)程序都有自己的目標(biāo)模塊的副本,這種代碼冗余存在的缺點(diǎn):

存儲(chǔ)同一個(gè)目標(biāo)模塊的多個(gè)副本會(huì)浪費(fèi)磁盤(pán)空間,并且所浪費(fèi)的空間是比較大的

如果使用了同一模塊的程序在同一時(shí)刻執(zhí)行,每個(gè)程序都有自己獨(dú)立的虛擬地址空間,其中保存了一份目標(biāo)代碼副本,這將會(huì)提供系統(tǒng)中虛擬內(nèi)存的整體使用量

如果需要修改一個(gè)靜態(tài)庫(kù)的一個(gè)目標(biāo)模塊,那么所有使用這個(gè)模塊的可執(zhí)行程序都必須重新進(jìn)行鏈接合并這個(gè)變更

共享庫(kù)就是為了克服靜態(tài)庫(kù)的諸多缺點(diǎn),它還具有的優(yōu)勢(shì)有:

由于整個(gè)程序的大小變得更小了,一些情況下,程序可以完全被加載到內(nèi)存中,從而能夠更快的啟動(dòng)程序,這一點(diǎn)只有在大型共享庫(kù)正被其他程序使用時(shí)才成立,第一個(gè)加載共享庫(kù)的程序?qū)嶋H上會(huì)在啟動(dòng)時(shí)花費(fèi)更長(zhǎng)的時(shí)間,因?yàn)楸仨氁日业焦蚕韼?kù)并將其加載到內(nèi)存中

目標(biāo)模塊修改是,不需要重新編譯程序就可以看到變更,甚至當(dāng)運(yùn)行著的程序正在使用共享庫(kù)的現(xiàn)有版本時(shí)也能夠進(jìn)行這樣的變更

共享庫(kù)的額外開(kāi)銷:

創(chuàng)建共享庫(kù)和構(gòu)建使用共享庫(kù)的程序比靜態(tài)庫(kù)更復(fù)雜

共享庫(kù)在編譯時(shí)需要使用位置獨(dú)立代碼,這在大多數(shù)架構(gòu)上會(huì)帶來(lái)性能開(kāi)銷,因?yàn)樗枰褂靡粋€(gè)額外的(寄存器)

在運(yùn)行時(shí)必須要執(zhí)行符號(hào)重定位,符號(hào)重定位期間,需要對(duì)共享庫(kù)中的每個(gè)符號(hào)(變量或函數(shù))的引用修改成符合在虛擬內(nèi)存中的實(shí)際運(yùn)行時(shí)位置,這個(gè)重定位的過(guò)程需要花費(fèi)一定的時(shí)間

雖然共享庫(kù)的代碼是多個(gè)進(jìn)程共享的,但是其中的變量不是,每個(gè)使用庫(kù)的進(jìn)程會(huì)擁有自己的在庫(kù)中定義的全局和靜態(tài)變量的副本。

3.1、創(chuàng)建和使用共享庫(kù)

創(chuàng)建一個(gè)共享庫(kù)

gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.cgcc-g-sharedlibfoo.somod1.omod2.omod3.o

貢獻(xiàn)庫(kù)的命名方式一般為libname.so

可以向之前構(gòu)建的共享庫(kù)中添加單個(gè)目標(biāo)模塊,也可以從中刪除單個(gè)目標(biāo)模塊

也可以將編譯共享庫(kù)的命令放在一行:

gcc-g-fPIC-Wallmod1.cmod2.cmod3.c-shared-olibfoo.so

位置獨(dú)立的代碼

-fPIC

選項(xiàng)指定編譯器應(yīng)該生成位置無(wú)關(guān)代碼,這會(huì)改變編譯器生成執(zhí)行文件特定操作的代碼方式,包括訪問(wèn)全局、靜態(tài)和外部變量,訪問(wèn)字符串常量,以及獲取函數(shù)的地址,這些改變使得代碼可以在運(yùn)行時(shí)放在任意虛擬地址處,這一點(diǎn)對(duì)于共享庫(kù)來(lái)說(shuō)是必須的,因?yàn)殒溄拥臅r(shí)候是無(wú)法知道共享庫(kù)代碼位于內(nèi)存何處。

在(linux)/x86-32上,可以使用不加-fPIC選項(xiàng)編譯的模塊來(lái)創(chuàng)建共享庫(kù),為了確定一個(gè)既有目標(biāo)文件在編譯時(shí)是否使用了-fPIC選項(xiàng),可以使用檢查目標(biāo)文件符號(hào)表中是否存在_GLOBAL_OFFSET_TABLE:

nmmod1.o|grep_GLOBAL_OFFSET_TABLEre(ad)elf-smod1.o|grep_GLOBAL_OFFSET_TABLE

下面的命令中如果產(chǎn)生了輸出,則說(shuō)明指定的共享庫(kù)中至少存在一個(gè)目標(biāo)模塊在編譯時(shí)沒(méi)有指定-fPIC:

objdump--all-heade(rs)libfoo.so|grep(TE)XTRELobjdump--all-headerslibfoo.so|grepTEXTREL

TEXTREL表示存在一個(gè)目標(biāo)模塊,其文本段中包含需要運(yùn)行時(shí)重定位的引用。

使用一個(gè)共享庫(kù)

為了使用共享庫(kù)需要做兩件事情,而使用靜態(tài)庫(kù)則無(wú)需完成這兩件事情:

可執(zhí)行文件中不包含它所需要的目標(biāo)文件的副本,因此需要通過(guò)某種機(jī)制找到運(yùn)行時(shí)所需要的共享庫(kù):鏈接階段將共享庫(kù)名稱嵌入可執(zhí)行文件中,一個(gè)程序所依賴的所有共享庫(kù)列表稱為程序的動(dòng)態(tài)依賴表

在程序運(yùn)行時(shí)需要某種機(jī)制解析嵌入的庫(kù)名,即找出與在可執(zhí)行文件中指定的名稱對(duì)應(yīng)的共享庫(kù)文件,如果庫(kù)不再內(nèi)存中的話就將庫(kù)加載進(jìn)內(nèi)存

運(yùn)行時(shí)解析內(nèi)嵌庫(kù)名的工作由動(dòng)態(tài)鏈接器(也稱為動(dòng)態(tài)鏈接加載器或運(yùn)行時(shí)加載器)來(lái)完成,動(dòng)態(tài)鏈接器本身也是一個(gè)共享庫(kù),其名稱為lib/ld-linux.so.2,所有使用共享庫(kù)的ELF可執(zhí)行文件都會(huì)用到這個(gè)共享庫(kù)。

lib/ld-linux.so.2通常是指向動(dòng)態(tài)鏈接器可執(zhí)行文件的符號(hào)鏈接,這個(gè)文件的名稱為ld-version.so。

動(dòng)態(tài)鏈接器會(huì)檢查程序所需的共享庫(kù)清單并使用一組預(yù)先定義好的規(guī)則來(lái)在文件系統(tǒng)上找出相關(guān)的庫(kù)文件。其中一些規(guī)則指定了一組存放共享庫(kù)的標(biāo)準(zhǔn)目錄,如/lib,/usr/lib。

LD_LIBRARY_PATH環(huán)境變量

通知?jiǎng)討B(tài)鏈接器一個(gè)共享庫(kù)位于一個(gè)非標(biāo)準(zhǔn)目錄中的一種方法是將該目錄添加到LD_LIBRARY_PATH

環(huán)境變量中以分號(hào)分隔的目錄列表中,如果定義了LD_LIBRARY_PATH,那么動(dòng)態(tài)鏈接器在查找標(biāo)準(zhǔn)庫(kù)目錄前會(huì)先查找該環(huán)境變量列出的目錄中的共享庫(kù)。

LD_LIBRARY_PATH=../prog#告知?jiǎng)討B(tài)鏈接器在當(dāng)前工作目錄中搜索共享庫(kù)

靜態(tài)鏈接和動(dòng)態(tài)鏈接的比較

術(shù)語(yǔ)鏈接通常指的是使用鏈接器ld將一個(gè)或多個(gè)編譯過(guò)的目標(biāo)文件合成一個(gè)可執(zhí)行程序,也稱為靜態(tài)鏈接。

在運(yùn)行時(shí)使用共享庫(kù)的可執(zhí)行程序需要經(jīng)歷額外的動(dòng)態(tài)鏈接階段。

3.2、共享庫(kù)soname

嵌入到可執(zhí)行程序以及動(dòng)態(tài)鏈接器在運(yùn)行時(shí)搜索的名稱除了使用真實(shí)名稱,還經(jīng)常使用別名來(lái)創(chuàng)建共享庫(kù),這種別名稱為soname,ELF中的

DT_SONAME

標(biāo)簽。

如果共享庫(kù)擁有一個(gè)soname,那么在靜態(tài)鏈接階段會(huì)將soname嵌入到可執(zhí)行文件中,而不會(huì)使用真實(shí)名稱,同時(shí)后面的動(dòng)態(tài)鏈接器在運(yùn)行時(shí)也會(huì)使用這個(gè)soname來(lái)搜索庫(kù),引入soname的目的是為了提供一個(gè)間接層,使得可執(zhí)行程序能夠在運(yùn)行時(shí)使用與鏈接時(shí)使用不同的但兼容的共享庫(kù)。

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)都是傳給鏈接器的指令,以將共享庫(kù)libfoo.so的soname設(shè)置為libbar.so

使用一下命令中的任意一個(gè),可以確定既有共享庫(kù)的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

鏈接器檢查到庫(kù)libfoo.so包含了soname:libbar.so,就將這個(gè)soname嵌入到可執(zhí)行文件中。

使用共享庫(kù)時(shí)必須要?jiǎng)?chuàng)建一個(gè)符號(hào)鏈接,將soname指向庫(kù)的真實(shí)名稱,并且必須要將這個(gè)符號(hào)鏈接放在動(dòng)態(tài)鏈接器搜索的其中一個(gè)目錄中。

程序載入內(nèi)存以設(shè)備執(zhí)行時(shí)發(fā)生的事情:

要找出一個(gè)進(jìn)程當(dāng)前使用的共享庫(kù)則可以列出相應(yīng)的Linux特有的/proc/(PI)D/maps文件中的內(nèi)容。

4、使用共享庫(kù)的有用工具

ldd

ldd

:列出動(dòng)態(tài)依賴,顯示一個(gè)程序運(yùn)行時(shí)所需要的共享庫(kù)。

ldd

會(huì)解析出每個(gè)庫(kù)引用,使用的搜索方式與動(dòng)態(tài)鏈接器一樣,并以下面的形式顯示結(jié)果:

library-name=>resolves-to-path

對(duì)于多數(shù)的ELF文件,ldd至少會(huì)列出與ld-linux.so.2、動(dòng)態(tài)鏈接器以及標(biāo)準(zhǔn)C庫(kù)lib.so.6相關(guān)的條目。

objdump和readelf

objdump

:用來(lái)從可執(zhí)行文件、編譯過(guò)的目標(biāo)、以及共享庫(kù)中獲取各類信息,包括反(匯編)的二進(jìn)制機(jī)器碼,還可以用來(lái)顯示這些文件各個(gè)ELF節(jié)的頭部信息,當(dāng)這樣使用時(shí),它就類似于readelf,readelf能顯示類似的信息,但是格式不同。

nm

nm命令會(huì)列出目標(biāo)庫(kù)或可執(zhí)行文件中定義的一組符號(hào),常用來(lái)尋找哪些庫(kù)定義了一個(gè)符號(hào)。

5、共享庫(kù)版本和命名規(guī)則

命名形式:

libname.somajor-id.minor-id

major-id:主要版本標(biāo)識(shí)符,區(qū)分兩個(gè)不兼容的版本

minor-id:次要版本可以是任意字符串,但是通常的形式是兩個(gè)由點(diǎn)分隔的數(shù)字,第一個(gè)數(shù)字表示次要版本,第二個(gè)數(shù)字表示該次要版本的補(bǔ)丁號(hào)或者修訂號(hào)

libdemo.so.1.0.1libdemo.so.1.0.2libdemo.so.2.0.0

共享庫(kù)的soname包括相應(yīng)的主版本標(biāo)識(shí)符,但是不包含次要版本標(biāo)識(shí)符,因此

soname的命名形式為:

libname.so.major-id

通常,會(huì)將soname

創(chuàng)建為包含真實(shí)名稱的目錄的一個(gè)相對(duì)符號(hào)鏈接:

libdemo.so.1

->libdemo.so.1.0.2libdemo.so.2

->libdemo.so.2.0.0

共享庫(kù)的一個(gè)主要版本可能有多個(gè)不同的次要版本,通常每個(gè)庫(kù)的主要版本的

soname

會(huì)指向主要版本中(最新)的次要版本,由于靜態(tài)鏈接階段會(huì)將soname

的副本(獨(dú)立于次要版本)嵌入到可執(zhí)行文件中,并且soname符號(hào)鏈接后面可能會(huì)被修改為指向更新的次要版本,從而確保在執(zhí)行期間能夠加載庫(kù)的最新的次要版本。

同一個(gè)庫(kù)的不同主要版本也能夠同時(shí)存在,被需要它們的程序分別訪問(wèn)。

除了真實(shí)名稱和soname之外,通常還會(huì)為每個(gè)共享庫(kù)定義第三個(gè)名稱:鏈接器名稱,將可執(zhí)行文件與共享庫(kù)鏈接起來(lái)時(shí)會(huì)使用這個(gè)名稱,鏈接器名稱是一個(gè)只包含庫(kù)名稱不包含主要版本和次要版本標(biāo)識(shí)符的符號(hào)鏈接,其形式為libname.so,有了鏈接器名稱之后就可以構(gòu)建能夠自動(dòng)使用共享庫(kù)(最新版)本的鏈接命令。

鏈接器名稱一般與它所引用的文件位于同一個(gè)目錄中,它既可以鏈接到真實(shí)名稱,也可以鏈接到庫(kù)的最新主要版本的soname。通常最好使用指向soname

的鏈接,從而對(duì)soname的修改會(huì)自動(dòng)反應(yīng)到鏈接器名稱。

如果需要使用一個(gè)舊版本的共享庫(kù),就不能使用鏈接器名稱,要使用真實(shí)名稱或者soname來(lái)指示出需要的版本。

5.1、使用標(biāo)準(zhǔn)規(guī)范創(chuàng)建一個(gè)共享庫(kù)

創(chuàng)建目標(biāo)文件

gcc-g-c-fPIC-Wallmod1.cmod2.cmod3.c

創(chuàng)建共享庫(kù),指定真實(shí)名稱和soname

gcc-g-shared-Wl,-soname,libdemo.so.1-olibdemo.so.1.0.1mod1.omod2.omod3.o

為soname和鏈接器名稱創(chuàng)建恰當(dāng)?shù)姆?hào)鏈接

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、安裝共享庫(kù)

共享庫(kù)及其關(guān)聯(lián)的符號(hào)鏈接一般會(huì)被安裝到一個(gè)標(biāo)準(zhǔn)目錄中,標(biāo)準(zhǔn)目錄包括:

/usr/lib:是大多數(shù)標(biāo)準(zhǔn)庫(kù)安裝的目錄

/lib:應(yīng)該將系統(tǒng)啟動(dòng)時(shí)用到的庫(kù)安裝到這個(gè)目錄,因?yàn)橄到y(tǒng)啟動(dòng)時(shí)可能還沒(méi)有掛載/usr/lib

/usr/local/lib:應(yīng)該將非標(biāo)準(zhǔn)或者實(shí)驗(yàn)性質(zhì)的庫(kù)安裝到這個(gè)目錄

/etc/ld.so.conf中列出的目錄

安裝完成后一般需要?jiǎng)?chuàng)建soname

和鏈接器名稱的符號(hào)鏈接:

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解決了共享庫(kù)的兩個(gè)潛在問(wèn)題:

共享庫(kù)可以位于各種目錄中,如果動(dòng)態(tài)鏈接器需要通過(guò)搜索這些目錄來(lái)找一個(gè)庫(kù)并加載這個(gè)庫(kù),整個(gè)過(guò)程將非常慢

當(dāng)安裝了新版本的庫(kù)或者刪除了舊版本的庫(kù),那么

soname符號(hào)鏈接就不是最新的

ldconfig可以通過(guò)執(zhí)行兩個(gè)任務(wù)來(lái)解決這些問(wèn)題:

它搜索一組標(biāo)準(zhǔn)的目錄并創(chuàng)建或更新一個(gè)緩存文件/etc/ld.so.cache使之包含在所有這些目錄中的主要版本(每個(gè)庫(kù)的主要版本的最新的次要版本)列表,動(dòng)態(tài)鏈接器在運(yùn)行時(shí)解析庫(kù)名稱時(shí)會(huì)輪流使用這個(gè)緩存文件:

為了構(gòu)建這個(gè)緩存,ldconfig會(huì)搜索在/etc/ld.so.conf中指定的目錄,然后搜索/lib和/usr/lib

`/etc/ld.so.conf文件由一個(gè)目錄路徑名(應(yīng)該是絕對(duì)路徑名)列表構(gòu)成,其中路徑名之間用換行、空格、制表符、逗號(hào)或冒號(hào)分隔

在一些發(fā)行版中,/usr/local/lib目錄也位于這個(gè)列表中

ldconfig-p會(huì)顯示/etc/ls.so.cache的當(dāng)前內(nèi)容

它檢查每個(gè)庫(kù)的各個(gè)主要版本的最新次要版本以找出嵌入的soname,然后在同一目錄中為每個(gè)soname創(chuàng)建(或更新)相對(duì)符號(hào)鏈接:

為了能夠正確執(zhí)行這些動(dòng)作,ldconfig要求庫(kù)的名稱要根據(jù)前面介紹的規(guī)范來(lái)命名:庫(kù)的真實(shí)名稱包含主要和次要標(biāo)識(shí)符,它們隨著庫(kù)的版本的更新而恰當(dāng)?shù)脑鲩L(zhǎng)

可以使用命令行選項(xiàng)來(lái)指定它執(zhí)行其中一個(gè)動(dòng)作:-N選項(xiàng)會(huì)防止緩存的重建,-X選項(xiàng)會(huì)阻止soname符號(hào)鏈接的創(chuàng)建。此外,-v(verbose)選項(xiàng)會(huì)使得ldconfig輸出描述其所執(zhí)行的動(dòng)作的信息

每當(dāng)安裝了一個(gè)新的庫(kù),更新或者刪除一個(gè)既有庫(kù),以及/etc/ld.so.conf中的目錄列表被修改后,都運(yùn)行相應(yīng)的ldconfig。

安裝一個(gè)庫(kù)的兩個(gè)不同主要版本:

mvlibdemo.so.1.0.1libdemo.so.2.0.0/usr/lib

為鏈接器名稱創(chuàng)建符號(hào)鏈接:

ln-slibdemo.so.2libdemo.so

如果更新庫(kù)的一個(gè)次要版本,由于鏈接器名稱指向了最新的soname,因此ldconfig還能取得保持鏈接器名稱的最新效果:

mvlibdemo.so.2.0.1/usr/lib

如果使用的是私有庫(kù),即沒(méi)有安裝在上述的標(biāo)準(zhǔn)目錄中的庫(kù),那么可以使用-n選項(xiàng)讓ldconfig創(chuàng)建soname,這個(gè)選項(xiàng)指定了只處理在命令行中列出的目錄的庫(kù),無(wú)需更新緩存文件。

使用ldconfig來(lái)處理當(dāng)前工作目錄中的庫(kù):

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、兼容與不兼容庫(kù)比較

滿足下列條件時(shí)表示修改過(guò)的庫(kù)與既有版本兼容:

庫(kù)中所有公共方法和變量的語(yǔ)義保持不變

沒(méi)有刪除庫(kù)的公共API中的函數(shù)和變量,但向公共API中添加新函數(shù)和變量

每個(gè)函數(shù)分配的結(jié)構(gòu)以及沒(méi)和函數(shù)的返回結(jié)構(gòu)保持不變

如果這些條件都滿足,更新庫(kù)時(shí)只需要調(diào)增既有庫(kù)的次要版本號(hào),否則就要?jiǎng)?chuàng)建新的主版本。

5.4、升級(jí)共享庫(kù)

共享庫(kù)的優(yōu)點(diǎn)之一就是當(dāng)一個(gè)運(yùn)行著的程序正在使用共享庫(kù)的一個(gè)既有版本時(shí),也能夠安裝新的主要版本或者次要版本的庫(kù),需要做的是:

創(chuàng)建新的庫(kù)版本,將其安裝到恰當(dāng)?shù)哪夸?/p>

根據(jù)需要更新soname和鏈接器名稱符號(hào)鏈接,或者使用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)文件中指定庫(kù)搜索目錄

通知?jiǎng)討B(tài)鏈接器共享庫(kù)的位置的方式:

LD_LIBRARY_PATH環(huán)境變量中指定

將共享庫(kù)安裝到標(biāo)準(zhǔn)庫(kù)目錄:/lib,/usr/lib,/etc/ls.so.conf中列出的其中一個(gè)目錄

第三種方式:在靜態(tài)編輯階段可以在執(zhí)行文件中插入一個(gè)在運(yùn)行時(shí)搜索共享庫(kù)的目錄列表,這種方式對(duì)于庫(kù)位于一個(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í)庫(kù)路徑列表中,在程序運(yùn)行時(shí),動(dòng)態(tài)鏈接器在解析共享庫(kù)引用時(shí)還會(huì)搜索這個(gè)路徑。

指定多個(gè)目錄:

多次指定-rpath選項(xiàng),所有這些列出的目錄會(huì)被鏈接成一個(gè)放到可執(zhí)行文件中的有序-rpath

列表

在一個(gè)-rpath選項(xiàng)中可以指定多個(gè)由分號(hào)分隔開(kāi)的目錄列表,運(yùn)行時(shí),動(dòng)態(tài)鏈接器會(huì)按照-rpath選項(xiàng)中指定的目錄順序來(lái)搜索目錄

-rpath的一個(gè)可替代方案就是使用LD_RUN_PARH環(huán)境變量,可以將由一個(gè)逗號(hào)分隔開(kāi)的目錄的字符串賦值給該變量,只有當(dāng)構(gòu)建可執(zhí)行文件時(shí)沒(méi)有指定-rpath選項(xiàng)才會(huì)使用LD_RUN_PATH

6.1、在構(gòu)建貢獻(xiàn)庫(kù)時(shí)使用-rpath鏈接器選項(xiàng)

假設(shè)有一個(gè)庫(kù)lib1.so依賴于另一個(gè)共享庫(kù)lib2.so,另外再假設(shè)這些庫(kù)分別位于非標(biāo)準(zhǔn)目錄d1和d2中:

首先在pdir/d2目錄中構(gòu)建libx2.so,這里省略了庫(kù)的版本號(hào)和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)的取值與庫(kù)的鏈接時(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è)庫(kù)位于一個(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

在鏈接主程序是,無(wú)需指定libx2.so,由于鏈接器能夠分析libx1.so中的rpath列表,因此它能夠找到libx2.so,同時(shí)在靜態(tài)鏈接階段解析出所有的符號(hào)。

可以通過(guò)readelf--dynamic或者等價(jià)的readelf-d命令的輸出來(lái)查看rpath列表。

6.2、ELFDT_RPATH和DT_RUNPATH條目

第一版ELF規(guī)范中,只有一種rpath列表能夠被嵌入到可執(zhí)行文件或共享庫(kù)中,對(duì)應(yīng)

ELF

文件中的DT_RPATH標(biāo)簽。后續(xù)的ELF舍棄了DT_RPATH,同時(shí)引入DT_RUNPATH來(lái)表示rpath列表,兩者的差別在于動(dòng)態(tài)鏈接器在運(yùn)行時(shí)搜索共享庫(kù)時(shí)它們相對(duì)于LD_LIBRARY_PATH環(huán)境變量的優(yōu)先級(jí),DT_RPATH的優(yōu)先級(jí)更高,DT_RUNPATH的優(yōu)先級(jí)更低。

默認(rèn)情況下,鏈接器將rpath列表創(chuàng)建為DT_RPATH標(biāo)簽。為了讓鏈接器將rpath列表創(chuàng)建為DT_RUNPATH條目必須使用--enable-new-dtags。

6.3、在rpath中使用$ORIGIN

應(yīng)用程序中使用了自身的共享庫(kù),但同時(shí)不希望強(qiáng)制要求將這些庫(kù)安裝在其中一個(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í)找出共享庫(kù)

在解析庫(kù)依賴時(shí),動(dòng)態(tài)鏈接器首先會(huì)檢查各個(gè)依賴字符串以確定它是否包含/,如果找到了一個(gè)斜線,那么依賴字符串就會(huì)被解釋成一個(gè)路徑名,并且會(huì)使用該路徑名加載庫(kù),否則動(dòng)態(tài)鏈接器會(huì)使用下面的規(guī)則來(lái)搜索共享庫(kù):

如果可執(zhí)行文件的DT_RPATH運(yùn)行時(shí)庫(kù)路徑列表中包含目錄并且不包含DT_RUNP

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論