成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux 動態庫相關知識總結

開發
動態庫和靜態庫在C/C++開發中很常見,相比靜態庫直接被編譯到可執行程序,動態庫運行時加載使得可執行程序的體積更小,更新動態庫可以不用重新 編譯可執行程序等諸多好處。作者是一個Linux后臺開發,這些知識經常用到,所以整理了一下這方面的知識。

動態庫和靜態庫在C/C++開發中很常見,相比靜態庫直接被編譯到可執行程序,動態庫運行時加載使得可執行程序的體積更小,更新動態庫可以不用重新 編譯可執行程序等諸多好處。作者是一個Linux后臺開發,這些知識經常用到,所以整理了一下這方面的知識。靜態庫相對簡單,本文只關心Linux平臺下 的動態庫。

[[156100]]

創建動態庫

這里我把一個短小卻很有用的哈希函數編譯成動態庫做為示例,ELFhash用于對字符串做哈希,返回一個無符號整數。

 

  1. //elfhash.h 
  2. #include 
  3. unsigned long  ELFhash(const char* key); 
  4.  
  5. //elfhash.c 
  6. #include "elfhash.h" 
  7. unsigned long ELFhash(const char* key)  
  8.   unsigned long h = 0, g; 
  9.   while( *key ) { 
  10.     h = ( h > 24
  11.     h &= ~g; 
  12.   return h; 

接下來使用gcc編譯以上代碼,并用ld將編譯的目標文件鏈接成動態庫

  1. gcc -fPIC -c -Wall elfhash.c  
  2. ld  -shared elfhash.o -o libelfhash.so 

其中-fPIC意思是生成位置無關的代碼(Position Independent Code),適用于動態庫,在多個進程中共享動態庫的同一份代碼。ld的-shared選項告訴鏈接器創建的是動態庫。gcc也可以間接調用ld生成動態庫

  1. gcc -fPIC -shared -Wall -o libelfhash.so elfhash.c 

使用動態庫

動態庫的使用方法有兩種一種是隱式使用,第二種是顯式使用。隱式使用的方法很簡單。

  1. #include "elfhash.h" 
  2. int main()  
  3.     printf("%ldn", ElfHash("key-for-test")); 
  4.     return 0

顯式使用動態庫需要借助以下幾個函數

#include
void *dlopen(const char *filename, int flag); //flag可以是RTLD_LAZY,執行共享庫中的代碼時解決未定義符號,RTLD_NOW則是dlopen返回前解決未定義符號。 
char *dlerror(void); //當發生錯誤時,返回錯誤信息 
void *dlsym(void *handle, const char *symbol); //獲取符號 
int dlclose(void *handle); //關閉

應用上面幾個函數,調用ELFhash實現跟隱式調用一樣的功能

  1. #include "elfhash.h" 
  2. #include 
  3. #include 
  4.  
  5. int main() {  
  6.     void *handle; 
  7.     unsigned long (*hash)(const char*); 
  8.     char *error; 
  9.     handle = dlopen ("./libelfhash.so", RTLD_LAZY); 
  10.     if (!handle) { 
  11.         fputs (dlerror(), stderr); 
  12.         exit(1); 
  13.     } 
  14.     hash = dlsym(handle, "ElfHash"); 
  15.     if ((error = dlerror()) != NULL)  { 
  16.          fputs(error, stderr); 
  17.          exit(1); 
  18.     } 
  19.     printf ("%ldn", (*hash)("key-for-test")); 
  20.     dlclose(handle); 

至此了解以上的知識就可以創建和使用動態庫了。 實際應用中我們可能還是會遇到一些問題。

動態庫的加載

動態庫創建那一節,我演示如何隱式使用動態庫,那么編譯運行這段代碼試一下。

gcc main.c -L./ -lelfhash 
./a.out //執行可執行程序
//以下是輸出結果
./a.out: error while loading shared libraries: libelfhash.so: cannot open shared object file: No such file or directory

結果運行時報錯,可執行程序找不到動態庫。 網上有一些說法是編譯時設置-L選項,但在Linux上面證明是不行的(SunOS上可行),這個選項只能在編譯鏈接時有效, 可以讓你使用-l如上面的-lelfhash。使用readelf -d a.out可以看到可執行文件依賴的動態庫信息。

 0x0000000000000001 (NEEDED)  Shared library: [libelfhash.so]

可以看到這里面并沒有包含動態庫的路徑信息。查閱一下動態鏈接器的文檔man ld-linux.so可以發現這樣一句話(有的沒有,版本問題)

If a slash is found, then the dependency string is interpreted as a (relative or absolute) pathname, and the library is loaded using that pathname

這段話太長,我只截取一部分,大致就是說,當依賴中有/符號,那么會被解析成動態庫加載的路徑,隱式使用的例子換一種編譯方法。

gcc main.c ./libelfhash.so 
./a.out
23621492 //輸出正常

再用readelf -d a.out查看會發現,依賴信息中有了一個路徑。

0x0000000000000001 (NEEDED)  Shared library: [./libelfhash.so]

這種方法雖然解決了問題,但是依賴中的路徑是硬編碼,不是很靈活。 動態鏈接器是如何查找的動態庫的需要進一步查閱文檔。關于查找的順序有點長,這里就不直接引用了,大致是這樣:

  • (僅ELF文件) 使用可執行文件中DT_RPATH區域設置的屬性,如果DT_RUNPATH被設置,那么忽略DT_RPATH(在我的Linux對應的是RPATH和RUNPATH)。

  • 使用環境變量LD_LIBRARY_PATH,如果可執行文件中有set-user-id/set-group-id, 會被忽略。

  • (僅ELF文件) 使用可執行文件中DT_RUNPATH區域設置的屬性

  • /etc/ld.so.cache緩存文件中查找

  • 從默認路徑/lib, /usr/lib文件目錄中查找

我們需要設置RPATH或者RUNPATH,可以這樣做

gcc main.c -Wl,-rpath,/home/xxx,--enable-new-dtags -L./  -lelfhash

這里的-Wl選項告訴鏈接器ld如果如何處理,接下來傳遞的-rpath(或者使用-R)告訴ld動態庫的路徑信息(注意-Wl,和后面選項之間不能有空格)。如果沒有--enable-new-dtags那么只會設置RPATH,反之,RPATH和RUNPATH會同時被設置。使用readelf -d a.out查看結果:

0x000000000000000f (RPATH)  Library rpath: [/home/xxx] 
0x000000000000001d (RUNPATH)  Library runpath: [/home/xxx]

如果使用環境變量LD_LIBRARY_PATH,那么一般這樣用 export

export LD_LIBRARY_PATH=/home/xxx;$LD_LIBRARY_PATH

RPATH和RUNPATH指定動態庫的路徑,用起來簡單,但是也缺乏靈活性,LDLIBRARYPATH在臨時測試的也是很有用的,但是在正式環境中,直接使用它也不是好的實踐,因為環境變量跟用戶的環境關系比較大。動態庫不僅要考慮自己使用, 還有分發給別的用戶使用的情況。

更通用的方法是使用ldconfig,有幾種方法,先在/etc/ld.so.conf.d/目錄下創建一個文件,然后把你的動態庫路徑寫進去。或者將你的動態庫放到/lib,/lib64(64位),/usr/lib,/usr/lib64(64位)然后運行sudo ldconfig重建/etc/ld.so.cache文件。

動態庫版本

通常在使用第三方給的動態庫的時候,都是帶有版本(文件命名),可以在/usr/lib64下看到很多這樣的動態庫。現在我重新編譯動態庫,這次加上版本信息。

gcc -fPIC -shared -Wall -Wl,-soname,libelfhash.so.0  -o libelfhash.so.0.0.0 elfhash.c

每個動態庫都有一個名字,如這里的libelfhash.so.0.0.0,叫real name,命名規則跟簡單,通常是libxxx.so.MAJOR.MINOR.VERSION(有 的時候VERSION會被省略),如果動態庫在接口上的兼容性,比如刪除了接口或者修改了接口參數,MAJOR增加,如果接口兼容,只是做了更新或者 bug修復那么MINOR和VERSION增加。也就是說MAJOR相同的庫接口都是兼容的,反之不兼容,如果使用不兼容的動態庫需要重新編譯可執行程 序。

編譯動態庫時,通過給ld傳遞連接選項-soname可以指定一個soname, 如這里的libelfhash.so.0 只保留MAJOR,可執行程序運行加載動態庫時,會加載這個指定名字的庫。

動態庫還有一個名字是link name,編譯可執行程序時,傳個鏈接器ld的動態庫名字,通常是沒有版本號以.so結尾的文件名。 一般作法是對soname創建軟鏈。

按照這個規則來命名的動態庫可以ldconfig識別,我們把libelfhash.so.0.0.0放到/usr/lib64文件夾中,執行以下指令

  1. $sudo ldconfig -v | grep libelfhash.so 
  2. libelfhash.so.0 -> libelfhash.so.0.0.0 

可以發現ldconfig根據libelfhash.so.0.0.0的信息,創建了一個soname指向real name的軟鏈,當動態庫更新(MINOR,VERSION增加),拷貝新庫到相應的位置,再執行sudo ldconfig會自動更新軟鏈指向***的動態庫,動態庫更新就完成了。

總結

OK,關于Linux動態庫知識整理就到這里了,這些知識雖說都是些基礎,少有涉及動態庫內部的一些原理,但是卻很常用。整理過程中我帶著疑問去閱讀了ldld-linux.so的文檔,收獲頗豐。同樣,希望本文能幫你解釋遇到的部分問題或疑惑。

責任編輯:王雪燕 來源: 左小田
相關推薦

2010-01-07 17:40:41

Linux動態庫

2009-01-11 09:14:45

Javascript開發總結

2010-03-18 14:24:31

云計算

2009-08-07 13:30:20

C# Excel導入

2010-03-01 16:31:59

Linux SNMP

2020-08-27 14:40:55

Linux內存內核

2021-01-04 09:50:09

前端數據技術

2021-02-06 23:03:58

SQLServer數據庫變量

2021-07-01 06:19:46

Redis數據庫API

2010-03-04 09:51:07

Linux動態庫

2011-07-29 11:32:16

路由PIM

2022-08-16 15:17:37

機器學習算法模型

2010-08-18 10:52:46

Linux筆試

2010-01-07 17:36:38

Linux靜態庫

2010-05-31 15:12:44

MySQL數據庫

2014-11-05 10:37:44

Windows Pho數據庫

2021-07-14 07:21:54

Linux遠程管理

2011-06-14 15:11:59

ORACLE

2021-03-24 14:50:00

SQLServer數據庫字符串

2011-08-18 17:05:16

Oracle數據庫的服
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人免费淫片aa视频免费 | 毛片在线免费 | 2020国产在线 | 国产美女在线观看 | 在线视频一区二区 | 精品国产欧美一区二区三区成人 | 91视频日本| 国产成人精品免高潮在线观看 | 99精品九九 | 亚洲成人av| 亚洲国产成人精品女人久久久 | 欧美精品综合在线 | 在线播放国产一区二区三区 | 欧美一级黄色网 | 欧美群妇大交群中文字幕 | 一级片视频免费 | 在线免费看91 | 亚洲精品久久久久久久久久久 | 亚洲精品中文在线观看 | 日韩a视频| 青草青草久热精品视频在线观看 | 久久精品91 | 欧美日韩精品在线免费观看 | 特级丰满少妇一级aaaa爱毛片 | 久草成人 | 99亚洲国产精品 | 欧美又大粗又爽又黄大片视频 | 九色国产 | 国产在线精品一区二区 | 91婷婷韩国欧美一区二区 | 国产 日韩 欧美 制服 另类 | 在线观看中文字幕av | 久久激情av | 欧美精品在线免费观看 | 欧美高清成人 | 亚洲精品成人av久久 | 国产成人精品一区二区三区网站观看 | 久久久精品一区二区三区 | 欧美欧美欧美 | 国精产品一区二区三区 | 精品国产一区二区在线 |