日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux下动态共享库加载时的搜索路径详解

發(fā)布時(shí)間:2025/4/16 linux 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux下动态共享库加载时的搜索路径详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對(duì)動(dòng)態(tài)庫(kù)的實(shí)際應(yīng)用還不太熟悉的讀者可能曾經(jīng)遇到過(guò)類(lèi)似“error while loading shared libraries”這樣的錯(cuò)誤,這是典型的因?yàn)樾枰膭?dòng)態(tài)庫(kù)不在動(dòng)態(tài)鏈接器ld.so的搜索路徑設(shè)置當(dāng)中導(dǎo)致的。?
具體說(shuō)來(lái),動(dòng)態(tài)鏈接器ld.so按照下面的順序來(lái)搜索需要的動(dòng)態(tài)共享庫(kù):?
1.ELF可執(zhí)行文件中動(dòng)態(tài)段中DT_RPATH所指定的路徑。這實(shí)際上是通過(guò)一種不算很常用,卻比較實(shí)用的方法所設(shè)置的:編譯目標(biāo)代碼時(shí),可以對(duì)gcc加入鏈接參數(shù)“-Wl,-rpath”指定動(dòng)態(tài)庫(kù)搜索路徑;?
2.環(huán)境變量LD_LIBRARY_PATH指定的動(dòng)態(tài)庫(kù)搜索路徑;?
3./etc/ld.so.cache中所緩存的動(dòng)態(tài)庫(kù)路徑(如果支持ld.so.cache的話)。這可以通過(guò)修改配置文件/etc/ld.so.conf中指定的動(dòng)態(tài)庫(kù)搜索路徑來(lái)改變;?
4.默認(rèn)的動(dòng)態(tài)庫(kù)搜索路徑/lib;?
5.默認(rèn)的動(dòng)態(tài)庫(kù)搜索路徑/usr/lib。?
?????? 在?
嵌入式Linux
系統(tǒng)的實(shí)際應(yīng)用中,1和2被經(jīng)常使用,也有一些相對(duì)簡(jiǎn)單的的嵌入式系統(tǒng)會(huì)采用4或5的路徑來(lái)規(guī)范動(dòng)態(tài)庫(kù)。3在嵌入式系統(tǒng)中使用的比較少,因?yàn)橛泻芏嘞到y(tǒng)根本就不支持ld.so.cache。?
??? 4和5的方式非常簡(jiǎn)單,只要將所需要的庫(kù)放到/lib或/usr/lib就可以解決找不到庫(kù)的問(wèn)題,不過(guò)對(duì)于大一些的系統(tǒng)來(lái)說(shuō),不太方便管理。1和2的方式要稍微復(fù)雜一些,下面我們用一個(gè)非常簡(jiǎn)單的例子來(lái)說(shuō)明如何應(yīng)用。?
首先編寫(xiě)一個(gè)最簡(jiǎn)單的動(dòng)態(tài)共享庫(kù),源代碼pirnt.c如下:?
???? 1? #include?
???? 2?
???? 3? void print_foo()?
???? 4? {?
???? 5????? printf("fooooooooo\n");?
???? 6? }?
注意將它編譯成共享庫(kù):?
# 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)用該共享庫(kù)main.c代碼如下:?
???? 1? #include?
???? 2?
???? 3? extern void print_foo();?
???? 4?
???? 5? int main()?
???? 6? {?
???? 7????? print_foo();?
???? 8??????????
???? 9????? return 0;?
??? 10? }?
編譯之后的運(yùn)行結(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?
這便是典型的找不到動(dòng)態(tài)庫(kù)的錯(cuò)誤。通常我們可以通過(guò)設(shè)置環(huán)境變量LD_LIBRARY_PATH來(lái)指定動(dòng)態(tài)庫(kù)的搜索路徑(即上面的方法2),比如這樣就可以正確運(yùn)行了:?
# export LD_LIBRARY_PATH=./?
# ./pfoo?
fooooooooo?
但這種方法有一個(gè)明顯的缺點(diǎn):一旦LD_LIBRARY_PATH被設(shè)定,則在這個(gè)環(huán)境變量生效的范圍之內(nèi),所有其他的ELF可執(zhí)行程序也會(huì)按照這個(gè)順序去搜索動(dòng)態(tài)庫(kù),這樣勢(shì)必會(huì)造成搜索時(shí)的一些浪費(fèi)。?
我們也可以使用另外一種方案來(lái)解決這種問(wèn)題,即利用參數(shù)“-Wl,-rpath”在編譯時(shí)指定運(yùn)行時(shí)的搜索路徑(即上面的方法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”的必要步驟,在這里只是為了說(shuō)明它已經(jīng)不再起作用了),而且”pfoo”程序運(yùn)行時(shí)也會(huì)發(fā)生找不到庫(kù)的錯(cuò)誤,而我們加入編譯參數(shù)“-Wl,-rpath,./”之后得到的pfoo_r程序則能正常運(yùn)行。?
事實(shí)上我們可以通過(guò)readelf工具來(lái)查看兩個(gè)文件的差異:?
# 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)???????????????????? 0x8049604?
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”可以用來(lái)查看ELF文件的動(dòng)態(tài)節(jié)(Dynamic Section)。對(duì)比pfoo 和pfoo_r的結(jié)果我們可以發(fā)現(xiàn),pfoo_r中多出來(lái)了RPATH項(xiàng),指定”Library rpath: [./]”。通過(guò)這種方式,我們可以用非常小的代價(jià)(僅增加幾乎可以忽略的空間開(kāi)銷(xiāo)),對(duì)每個(gè)ELF文件都指定最優(yōu)化的搜索路徑,達(dá)到提升性能的目的。這是我們比較推薦的一種方法。當(dāng)然了,具體如果操作依賴(lài)于具體的軟件系統(tǒng)的情況,簡(jiǎn)單的系統(tǒng)中直接將所有的庫(kù)都放到/lib下也未嘗不是一種簡(jiǎn)單易行的優(yōu)化方案。

?

轉(zhuǎn)載http://www.cnblogs.com/skyofbitbit/p/3688299.html

轉(zhuǎn)載于:https://www.cnblogs.com/bigbear1385/p/6638249.html

總結(jié)

以上是生活随笔為你收集整理的Linux下动态共享库加载时的搜索路径详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。