當(dāng)前位置:首頁 > 嵌入式 > 嵌入式軟件

對動態(tài)庫的實際應(yīng)用還不太熟悉的讀者可能曾經(jīng)遇到過類似“error while loading shared libraries”這樣的錯誤,這是典型的因為需要的動態(tài)庫不在動態(tài)鏈接器ld.so的搜索路徑設(shè)置當(dāng)中導(dǎo)致的。

具體說來,動態(tài)鏈接器ld.so按照下面的順序來搜索需要的動態(tài)共享庫:

1.ELF可執(zhí)行文件中動態(tài)段中DT_RPATH所指定的路徑。這實際上是通過一種不算很常用,卻比較實用的方法所設(shè)置的:編譯目標(biāo)代碼時,可以對gcc加入鏈接參數(shù)“-Wl,-rpath”指定動態(tài)庫搜索路徑;

2.環(huán)境變量LD_LIBRARY_PATH指定的動態(tài)庫搜索路徑;

3./etc/ld.so.cache中所緩存的動態(tài)庫路徑(如果支持ld.so.cache的話)。這可以通過修改配置文件/etc/ld.so.conf中指定的動態(tài)庫搜索路徑來改變;

4.默認(rèn)的動態(tài)庫搜索路徑/lib;

5.默認(rèn)的動態(tài)庫搜索路徑/usr/lib。

在嵌入式Linux系統(tǒng)的實際應(yīng)用中,1和2被經(jīng)常使用,也有一些相對簡單的的嵌入式系統(tǒng)會采用4或5的路徑來規(guī)范動態(tài)庫。3在嵌入式系統(tǒng)中使用的比較少,因為有很多系統(tǒng)根本就不支持ld.so.cache。

4和5的方式非常簡單,只要將所需要的庫放到/lib或/usr/lib就可以解決找不到庫的問題,不過對于大一些的系統(tǒng)來說,不太方便管理。1和2的方式要稍微復(fù)雜一些,下面我們用一個非常簡單的例子來說明如何應(yīng)用。

首先編寫一個最簡單的動態(tài)共享庫,源代碼pirnt.c如下:

1 #include <STdio.h>

2

3 void print_foo()

4 {

5 printf("fooooooooo\n");

6 }

注意將它編譯成共享庫:

# gcc print.c -shared -o libprint.so

# file libprint.so

libprint.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped

調(diào)用該共享庫main.c代碼如下:

1 #include <stdio.h>

2

3 extern void print_foo();

4

5 int main()

6 {

7 print_foo();

8

9 return 0;

10 }

編譯之后的運行結(jié)果如下:

# gcc main.c -L./ -lprint -o pfoo

# ./pfoo

./pfoo: error while loading shared libraries: libprint.so: cannot open shared object file: No such file or directory

這便是典型的找不到動態(tài)庫的錯誤。通常我們可以通過設(shè)置環(huán)境變量LD_LIBRARY_PATH來指定動態(tài)庫的搜索路徑(即上面的方法2),比如這樣就可以正確運行了:

# export LD_LIBRARY_PATH=./

# ./pfoo

fooooooooo

但這種方法有一個明顯的缺點:一旦LD_LIBRARY_PATH被設(shè)定,則在這個環(huán)境變量生效的范圍之內(nèi),所有其他的ELF可執(zhí)行程序也會按照這個順序去搜索動態(tài)庫,這樣勢必會造成搜索時的一些浪費。

我們也可以使用另外一種方案來解決這種問題,即利用參數(shù)“-Wl,-rpath”在編譯時指定運行時的搜索路徑(即上面的方法1),如下所示:

# unset LD_LIBRARY_PATH

# echo $LD_LIBRARY_PATH

# gcc main.c -L./ -lprint -o pfoo_r -Wl,-rpath=./

# ./pfoo

./pfoo: error while loading shared libraries: libprint.so: cannot open shared object file: No such file or directory

# ./pfoo_r

fooooooooo

我們首先unset了LD_LIBRARY_PATH,可以看到它已經(jīng)不再有效了(當(dāng)然這不是使用參數(shù)“-Wl,-rpath”的必要步驟,在這里只是為了說明它已經(jīng)不再起作用了),而且”pfoo”程序運行時也會發(fā)生找不到庫的錯誤,而我們加入編譯參數(shù)“-Wl,-rpath,./”之后得到的pfoo_r程序則能正常運行。

事實上我們可以通過readelf工具來查看兩個文件的差異:

# readelf -d pfoo

Dynamic segment at offset 0x514 contains 21 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libprint.so]

0x00000001 (NEEDED) Shared library: [libc.so.6]

0x0000000c (INIT) 0x8048344

0x0000000d (FINI) 0x80484e0

0x00000004 (HASH) 0x8048128

0x00000005 (STRTAB) 0x8048240

0x00000006 (SYMTAB) 0x8048170

0x0000000a (STRSZ) 178 (bytes)

0x0000000b (SYMENT) 16 (bytes)

0x00000015 (DEBUG) 0x0

0x00000003 (PLTGOT) 0x80495f8

0x00000002 (PLTRELSZ) 16 (bytes)

0x00000014 (PLTREL) REL

0x00000017 (JMPREL) 0x8048334

0x00000011 (REL) 0x804832c

0x00000012 (RELSZ) 8 (bytes)

0x00000013 (RELENT) 8 (bytes)

0x6ffffffe (VERNEED) 0x804830c

0x6fffffff (VERNEEDNUM) 1

0x6ffffff0 (VERSYM) 0x80482f2

0x00000000 (NULL) 0x0

[root@localhost ldpath]# readelf -d pfoo_r

Dynamic segment at offset 0x518 contains 22 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libprint.so]

0x00000001 (NEEDED) Shared library: [libc.so.6]

0x0000000f (RPATH) Library rpath: [./]

0x0000000c (INIT) 0x8048348

0x0000000d (FINI) 0x80484e4

0x00000004 (HASH) 0x8048128

0x00000005 (STRTAB) 0x8048240

0x00000006 (SYMTAB) 0x8048170

0x0000000a (STRSZ) 181 (bytes)

0x0000000b (SYMENT) 16 (bytes)

0x00000015 (DEBUG) 0x0

0x00000003 (PLTGOT) 0x8049*

0x00000002 (PLTRELSZ) 16 (bytes)

0x00000014 (PLTREL) REL

0x00000017 (JMPREL) 0x8048338

0x00000011 (REL) 0x8048330

0x00000012 (RELSZ) 8 (bytes)

0x00000013 (RELENT) 8 (bytes)

0x6ffffffe (VERNEED) 0x8048310

0x6fffffff (VERNEEDNUM) 1

0x6ffffff0 (VERSYM) 0x80482f6

0x00000000 (NULL) 0x0

“readelf -d”可以用來查看ELF文件的動態(tài)節(jié)(Dynamic Section)。對比pfoo 和pfoo_r的結(jié)果我們可以發(fā)現(xiàn),pfoo_r中多出來了RPATH項,指定”Library rpath: [./]”。通過這種方式,我們可以用非常小的代價(僅增加幾乎可以忽略的空間開銷),對每個ELF文件都指定最優(yōu)化的搜索路徑,達到提升性能的目的。這是我們比較推薦的一種方法。當(dāng)然了,具體如果操作依賴于具體的軟件系統(tǒng)的情況,簡單的系統(tǒng)中直接將所有的庫都放到/lib下也未嘗不是一種簡單易行的優(yōu)化方案。



miaomi

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉