Llinux下動(dòng)態(tài)鏈接庫(kù)及靜態(tài)鏈接庫(kù)的實(shí)用和生成

https://mbb.eet-china.com/forum/topic/77827_1_1.html

1. 庫(kù)簡(jiǎn)介

庫(kù)有動(dòng)態(tài)與靜態(tài)兩種苛败,動(dòng)態(tài)通常用.so為后綴水孩,靜態(tài)用.a為后綴镰矿。例如:libhello.solibhello.a俘种。

為了在同一系統(tǒng)中使用不同版本的庫(kù)秤标,可以在庫(kù)文件名后加上版本號(hào)為后綴,例如: libhello.so.1.0。由于程序連接默認(rèn)以.so為文件后綴名安疗。所以為了使用這些庫(kù)抛杨,通常使用建立符號(hào)連接的方式。

ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so

2. 使用庫(kù)

當(dāng)要使用靜態(tài)的程序庫(kù)時(shí)荐类,連接器會(huì)找出程序所需的函數(shù)怖现,然后將它們拷貝到執(zhí)行文件,由于這種拷貝是完整的,所以一旦連接成功屈嗤,靜態(tài)程序庫(kù)也就不再需要了潘拨。然 而,對(duì)動(dòng)態(tài)庫(kù)而言饶号,就不是這樣铁追。動(dòng)態(tài)庫(kù)會(huì)在執(zhí)行程序內(nèi)留下一個(gè)標(biāo)記‘指明當(dāng)程序執(zhí)行時(shí),首先必須載入這個(gè)庫(kù)茫船。由于動(dòng)態(tài)庫(kù)節(jié)省空間琅束,Linux下進(jìn)行連接的 缺省操作是首先連接動(dòng)態(tài)庫(kù),也就是說(shuō)算谈,如果同時(shí)存在靜態(tài)和動(dòng)態(tài)庫(kù)涩禀,不特別指定的話,將與動(dòng)態(tài)庫(kù)相連接然眼。
現(xiàn)在假設(shè)有一個(gè)叫hello的程序開(kāi)發(fā)包艾船,它提供一個(gè)靜態(tài)庫(kù)libhello.a,一個(gè)動(dòng)態(tài)庫(kù)libhello.so高每,一個(gè)頭文件hello.h屿岂。頭文件中提供sayhello()這個(gè)函數(shù)。

/* hello.h */
void sayhello();

另外還有一些說(shuō)明文檔鲸匿。這是一個(gè)典型的程序開(kāi)發(fā)包結(jié)構(gòu)爷怀。

2.1 與動(dòng)態(tài)庫(kù)連接

Linux默認(rèn)的就是與動(dòng)態(tài)庫(kù)連接,下面這段程序testlib.c使用hello庫(kù)中的sayhello()函數(shù)带欢。

/*testlib.c*/
#include
#include
int main()
{
    sayhello();
    return 0;
}

使用如下命令進(jìn)行編譯

$gcc -c testlib.c -o testlib.o

用如下命令連接:

$gcc testlib.o -lhello -o testlib

在連接時(shí)要注意霉撵,假設(shè)libhello.solibhello.a都在缺省的庫(kù)搜索路徑下/usr/lib下,如果在其它位置要加上-L參數(shù)洪囤。

2.2 與靜態(tài)庫(kù)連接

與與靜態(tài)庫(kù)連接麻煩一些,主要是參數(shù)問(wèn)題撕氧。還是上面的例子:

$gcc testlib.o -o testlib -WI,-Bstatic -lhello

注:這個(gè)特別的-WI, -Bstatic參數(shù)瘤缩,實(shí)際上是傳給了連接器ld,指示它與靜態(tài)庫(kù)連接伦泥。如果系統(tǒng)中只有靜態(tài)庫(kù)當(dāng)然就不需要這個(gè)參數(shù)了剥啤。

如果要和多個(gè)庫(kù)相連接,而每個(gè)庫(kù)的連接方式不一樣不脯,比如上面的程序既要和libhello進(jìn)行靜態(tài)連接府怯,又要和libbye進(jìn)行動(dòng)態(tài)連接,其命令應(yīng)為:

$gcc testlib.o -o testlib -WI,-Bstatic -lhello -WI,-Bdynamic -lbye

3. 動(dòng)態(tài)庫(kù)的路徑問(wèn)題

為了讓執(zhí)行程序順利找到動(dòng)態(tài)庫(kù)防楷,有三種方法:

  • 把庫(kù)拷貝到/usr/lib/lib目錄下牺丙。

  • LD_LIBRARY_PATH環(huán)境變量中加上庫(kù)所在路徑。例如動(dòng)態(tài)庫(kù)libhello.so/home/ting/lib目錄下,以bash為例冲簿,使用命令:

    \$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib
    
  • 修改/etc/ld.so.conf文件粟判,把庫(kù)所在的路徑加到文件末尾,并執(zhí)行ldconfig刷新峦剔。這樣档礁,加入的目錄下的所有庫(kù)文件都可見(jiàn)

4. 查看庫(kù)中的符號(hào)

有時(shí)候可能需要查看一個(gè)庫(kù)中到底有哪些函數(shù),nm命令可以打印出庫(kù)中的涉及到的所有符號(hào)吝沫。庫(kù)既可以是靜態(tài)的也可以是動(dòng)態(tài)的呻澜。nm列出的符號(hào)有很多,常見(jiàn)的有 三種惨险,一種是在庫(kù)中被調(diào)用羹幸,但并沒(méi)有在庫(kù)中定義(表明需要其他庫(kù)支持),用U表示平道;一種是庫(kù)中定義的函數(shù)睹欲,用T表示,這是最常見(jiàn)的一屋;另外一種是所謂的“弱態(tài)”符號(hào)窘疮,它們雖然在庫(kù)中被定義,但是可能被其他庫(kù)中的同名符號(hào)覆蓋冀墨,用W表示闸衫。例如,假設(shè)開(kāi)發(fā)者希望知道上央提到的hello庫(kù)中是否定義了printf()

$nm libhello.so |grep printf
U printf

U表示符號(hào)printf被引用诽嘉,但是并沒(méi)有在函數(shù)內(nèi)定義蔚出,由此可以推斷,要正常使用hello庫(kù)虫腋,必須有其它庫(kù)支持骄酗,再使用ldd命令查看hello依賴(lài)于哪些庫(kù):

$ldd hello
libc.so.6=>/lib/libc.so.6(0x400la000)
/lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)

從上面的結(jié)果可以繼續(xù)查看printf最終在哪里被定義,有興趣可以go on

5. 生成庫(kù)

第一步要把源代碼編繹成目標(biāo)代碼悦冀。以下面的代碼為例趋翻,生成上面用到的hello庫(kù):

/* hello.c */
#include
void sayhello()
{
    printf("hello,world\n");
}

gcc編繹該文件,在編繹時(shí)可以使用任何全法的編繹參數(shù)盒蟆,例如-g加入調(diào)試代碼等:

gcc -c hello.c -o hello.o

5.1 連接成靜態(tài)庫(kù)

連接成靜態(tài)庫(kù)使用ar命令踏烙,其實(shí)ararchive的意思

$ar cqs libhello.a hello.o

5.2 連接成動(dòng)態(tài)庫(kù)

生成動(dòng)態(tài)庫(kù)用gcc來(lái)完成,由于可能存在多個(gè)版本历等,因此通常指定版本號(hào):

$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o

另外再建立兩個(gè)符號(hào)連接:

$ln -s libhello.so.1.0 libhello.so.1
$ln -s libhello.so.1 libhello.so

這樣一個(gè)libhello的動(dòng)態(tài)連接庫(kù)就生成了讨惩。最重要的是傳gcc -shared參數(shù)使其生成是動(dòng)態(tài)庫(kù)而不是普通執(zhí)行程序。

-Wl表示后面的參數(shù)也就是-soname寒屯,libhello.so.1直接傳給連接器ld進(jìn)行處理荐捻。實(shí)際上,每一個(gè)庫(kù)都有一個(gè)soname,當(dāng)連接器發(fā)現(xiàn)它正 在查找的程序庫(kù)中有這樣一個(gè)名稱(chēng)靴患,連接器便會(huì)將soname嵌入連結(jié)中的二進(jìn)制文件內(nèi)仍侥,而不是它正在運(yùn)行的實(shí)際文件名,在程序執(zhí)行期間鸳君,程序會(huì)查找擁有soname名字的文件农渊,而不是庫(kù)的文件名,換句話說(shuō)或颊,soname是庫(kù)的區(qū)分標(biāo)志砸紊。

這樣做的目的主要是允許系統(tǒng)中多個(gè)版本的庫(kù)文件共存,習(xí)慣上在命名庫(kù)文件的時(shí)候通常與soname相同:

libxxxx.so.major.minor

其中囱挑,xxxx是庫(kù)的名字醉顽,major是主版本號(hào),minor是次版本號(hào) 平挑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末游添,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子通熄,更是在濱河造成了極大的恐慌唆涝,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唇辨,死亡現(xiàn)場(chǎng)離奇詭異廊酣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)赏枚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)亡驰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人饿幅,你說(shuō)我怎么就攤上這事凡辱。” “怎么了栗恩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵煞茫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我摄凡,道長(zhǎng),這世上最難降的妖魔是什么蚓曼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任亲澡,我火速辦了婚禮,結(jié)果婚禮上纫版,老公的妹妹穿的比我還像新娘床绪。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布癞己。 她就那樣靜靜地躺著膀斋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痹雅。 梳的紋絲不亂的頭發(fā)上仰担,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音绩社,去河邊找鬼摔蓝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愉耙,可吹牛的內(nèi)容都是我干的贮尉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼朴沿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼猜谚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起赌渣,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤魏铅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锡垄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沦零,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年货岭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了路操。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡千贯,死狀恐怖屯仗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搔谴,我是刑警寧澤魁袜,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站敦第,受9級(jí)特大地震影響峰弹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芜果,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一鞠呈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧右钾,春花似錦蚁吝、人聲如沸旱爆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)怀伦。三九已至,卻和暖如春山林,著一層夾襖步出監(jiān)牢的瞬間房待,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伏穆。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓翎迁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354