Linux動態庫.so文件加載搜索路徑詳解


因為這一段要集成代碼,除了組內的,還有組間的,還有第三方的,這里面都采用動態庫的方式進行鏈接,但是在集成的時候經常出現so文件找不到的問題,使用ldd查看,也是某些so文件找不到。有的文件明明就在那里,但是卻找不到,針對這些麻煩,我們頭疼醫頭腳疼醫腳,暫時解決了這些問題,但是並沒有從根本上了解清楚,解決思路單一,都是修改ld.so.conf文件,然后執行ldconfig。今天看了帖子,就順便把這個so文件查找順序的問題徹底了解了,省得后面再出問題的時候,又修改ld.so.conf去解決。

首先,我們要知道so文件是怎么查找的。

 動態鏈接器ld-linux.so按照下面的順序來搜索需要的動態共享庫對於elf格式的可執行程序,是由ld-linux.so*來完成的,它先后搜索elf文件的DT_RPATH段(不可控) -->  環境變量LD_LIBRARY_PATH --> /etc/ld.so.cache文件列表 --> /lib/和/usr/lib 目錄找到庫文件后載入內存。

1.ELF可執行文件中動態段中DT_RPATH所指定的路徑。這實際上是通過一種不算很常用,卻比較實用的方法所設置的:編譯目標代碼時,可以對gcc/g++加入鏈接參數“-Wl,-rpath”指定動態庫搜索路徑; 實際上,這種方式我們基本沒用過,所以這個查找方式基本不會起作用。
2.環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑;一般需要修改用戶的bashrc或者系統的profile文件 ,一般小程序也不會修改這倆文件,除非是對於/usr/local/lib這種通用的路徑,有可能會放進去,但也不一定。
3./etc/ld.so.cache中所緩存的動態庫路徑(如果支持ld.so.cache的話,這個文件還不小有幾百k,有一大堆具體的so文件)。這可以通過修改配置文件/etc/ld.so.conf中指定的動態庫搜索路徑來改變; 
4.默認的動態庫搜索路徑/lib或者是/lib64; 
5.默認的動態庫搜索路徑/usr/lib或者是/usr/lib64

簡單例子 printf.cpp

 
#include <iostream>
void Print()
{
 std::cout<< "Hello,world!"<<std::endl;
}

動態庫編譯

 g++ printf.cpp -shared -fPIC -o libprintf.so

 main.cpp

 
#include <iostream>
#include <printf.cpp>
extern void Print();
int main()
{
  Print();
  return 0;
}

1)指定動態庫的搜索路徑為當前本地路徑

g++ main.cpp -L./  -lprintf -Wl,-rpath=./

查看可執行程序,內部的細節

 
readelf -d a.out
Dynamic section at offset 0xe08 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libprintf.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [./]

指定了動態庫鏈接的位置

2)增加系統變量

 
export LD_LIBRARY_PATH=./ 
g++ main.cpp -L./  -lprintf

去掉指定目錄指令

unset LD_LIBRARY_PATH 
echo $LD_LIBRARY_PATH 

所以,修復so文件找不到的方法就是將動態庫所在目錄的絕對路徑加到動態載入器搜索序的任一次序中,下面說具體實現方法:

方法1:拷貝自己制作的共享庫到/lib或/usr/lib,不推薦

方法2:將動態庫所在目錄的絕對路徑添加到系統環境變量中

     2.1、將動態庫所在目錄的絕對路徑臨時添加到環境變量中(隨終端關閉失效)

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/chiliast/homework/day03/shared/lib

    2.2、將動態庫所在目錄的絕對路徑設置到~/.bashrc或/etc/profile中(永久生效)

         用戶級別:追加庫路徑到~/.bashrc文件尾

        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/chiliast/homework/day03/shared/lib
        source ~/.bashrc 或 . ~/.bashrc使配置生效

        系統級別:追加庫路徑到/etc/profile文件尾

        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/chiliast/homework/day03/shared/lib
        source /etc/profile 或 ./etc/profile使配置生效

方法3:將動態庫所在目錄的絕對路徑添加到 /etc/ld.so.cache文件中(2步實現)

         編輯/etc/ld.so.conf文件,加入庫文件所在目錄的路徑

        運行ldconfig (需要super user權限),該命令會重建/etc/ld.so.cache文件


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM