dlopen及so動(dòng)態(tài)加載原理_第1頁(yè)
dlopen及so動(dòng)態(tài)加載原理_第2頁(yè)
dlopen及so動(dòng)態(tài)加載原理_第3頁(yè)
dlopen及so動(dòng)態(tài)加載原理_第4頁(yè)
dlopen及so動(dòng)態(tài)加載原理_第5頁(yè)
已閱讀5頁(yè),還剩1頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Linux提供了一套API來(lái)動(dòng)態(tài)裝載庫(kù)。下面列出了這些API:- dlopen,打開(kāi)一個(gè)庫(kù),并為使用該庫(kù)做些準(zhǔn)備。- dlsym,在打開(kāi)的庫(kù)中查找符號(hào)的值。- dlclose,關(guān)閉庫(kù)。- dlerror,返回一個(gè)描述最后一次調(diào)用dlopen、dlsym,或dlclose的錯(cuò)誤信息的字符串。C語(yǔ)言用戶需要包含頭文件dlfcn.h才能使用上述API。glibc還增加了兩個(gè)POSIX標(biāo)準(zhǔn)中沒(méi)有的API:- dladdr,從函數(shù)指針解析符號(hào)名稱和所在的文件。- dlvsym,與dlsym類似,只是多了一個(gè)版本字符串參數(shù)。在Linux上,使用動(dòng)態(tài)鏈接的應(yīng)用程序需要和庫(kù)libdl.so一起鏈接,也就是使用

2、選項(xiàng)-ldl。但是,編譯時(shí)不需要和動(dòng)態(tài)裝載的庫(kù)一起鏈接。程序3-1是一個(gè)在Linux上使用dl*例程的簡(jiǎn)單示例。延遲重定位(Lazy Relocation)延遲重定位/裝載是一個(gè)允許符號(hào)只在需要時(shí)才重定位的特性。這常在各UNIX系統(tǒng)上解析函數(shù)調(diào)用時(shí)用到。當(dāng)一個(gè)和共享庫(kù)一起鏈接的應(yīng)用程序幾乎不會(huì)用到該共享庫(kù)中的函數(shù)時(shí),該特性被證明是非常有用的。這種情況下,只有庫(kù)中的函數(shù)被應(yīng)用程序調(diào)用時(shí),共享庫(kù)才會(huì)被裝載,否則不會(huì)裝載,因此會(huì)節(jié)約一些系統(tǒng)資源。但是如果把環(huán)境變量LD_BIND_NOW設(shè)置成一個(gè)非空值,所有的重定位操作都會(huì)在程序啟動(dòng)時(shí)進(jìn)行。也可以在鏈接器命令行通過(guò)使用-z now鏈接器選項(xiàng)使延遲綁定

3、對(duì)某個(gè)特定的共享庫(kù)失效。需要注意的是,除非重新鏈接該共享庫(kù),否則對(duì)該共享庫(kù)的這種設(shè)置會(huì)一直有效。初始化(initializing)和終止化(finalizing)函數(shù)有時(shí)候,以前的代碼可能用到了兩個(gè)特殊的函數(shù):_init和_fini。_init和_fini函數(shù)用在裝載和卸載某個(gè)模塊(注釋14)時(shí)分別控制該模塊的構(gòu)造器和析構(gòu)器(或構(gòu)造函數(shù)和析構(gòu)函數(shù))。他們的C語(yǔ)言原型如下:void _init(void);void _fini(void);當(dāng)一個(gè)庫(kù)通過(guò)dlopen()動(dòng)態(tài)打開(kāi)或以共享庫(kù)的形式打開(kāi)時(shí),如果_init在該庫(kù)中存在且被輸出出來(lái),則_init函數(shù)會(huì)被調(diào)用。如果一個(gè)庫(kù)通過(guò)dlclose()

4、動(dòng)態(tài)關(guān)閉或因?yàn)闆](méi)有應(yīng)用程序引用其符號(hào)而被卸載時(shí),_fini函數(shù)會(huì)在庫(kù)卸載前被調(diào)用。當(dāng)使用你自己的_init和_fini函數(shù)時(shí),需要注意不要與系統(tǒng)啟動(dòng)文件一起鏈接??梢允褂肎CC選項(xiàng) -nostartfiles 做到這一點(diǎn)。但是,使用上面的函數(shù)或GCC的-nostartfiles選項(xiàng)并不是很好的習(xí)慣,因?yàn)檫@可能會(huì)產(chǎn)生一些意外的結(jié)果。相反,庫(kù)應(yīng)該使用_attribute_(constructor)和_attribute_(destructor)函數(shù)屬性來(lái)輸出它的構(gòu)造函數(shù)和析構(gòu)函數(shù)。如下所示:void _attribute_(constructor) x_init(void)void _attrib

5、ute_(destructor) x_fini(void)構(gòu)造函數(shù)會(huì)在dlopen()返回前或庫(kù)被裝載時(shí)調(diào)用。析構(gòu)函數(shù)會(huì)在這樣幾種情況下被調(diào)用:dlclose()返回前,或main()返回后,或裝載庫(kù)過(guò)程中exit()被調(diào)用時(shí)。我們通過(guò)一個(gè)例子來(lái)講解dlopen系列函數(shù)的使用和操作:主程序:1. #include <stdlib.h>2. #include <dlfcn.h>3. #include <stdio.h>4.5. /申明結(jié)構(gòu)體6. typedef struct _test 7.   &#

6、160; int i;8.     void (* echo_fun)(struct _test *p);9. Test;10.11. /供動(dòng)態(tài)庫(kù)使用的注冊(cè)函數(shù)12. void _register(Test *p) 13.     p->i = 1;14.     p->echo_fun(p);15. 16.17. int main(void) 18.19

7、.     void *handle = NULL;20.     char *myso = "./mylib.so"21.22.     if(handle = dlopen(myso, RTLD_NOW) = NULL) 23.         print

8、f("dlopen - %sn", dlerror();24.         exit(-1);25.     26.27.     return 0;28. 動(dòng)態(tài)庫(kù):1. #include <stdio.h>2. #include <stdlib.h>3.4. /申明結(jié)構(gòu)體類型5. typedef struct _test 6.  

9、0;  int i;7.     void (*echo_fun)(struct _test *p);8. Test;9.10. /申明注冊(cè)函數(shù)原型11. void _register(Test *p);12.13. static void _printf(Test *p) 14.     printf("i = %dn", p->i);15. 16.17. /動(dòng)態(tài)庫(kù)申請(qǐng)一個(gè)全局變量空間18. /這種

10、 ".成員"的賦值方式為c99標(biāo)準(zhǔn)19. static Test config = 20.     .i = 0,21.     .echo_fun = _printf,22. ;23.24. /加載動(dòng)態(tài)庫(kù)的自動(dòng)初始化函數(shù)25. void _init(void) 26.     printf("initn");27.    &#

11、160;/調(diào)用主程序的注冊(cè)函數(shù)28.     _register(&config);29. 主程序編譯: gcc test.c -ldl -rdynamic動(dòng)態(tài)庫(kù)編譯: gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c主程序通過(guò)dlopen()加載一個(gè).so的動(dòng)態(tài)庫(kù)文件, 然后動(dòng)態(tài)庫(kù)會(huì)自動(dòng)運(yùn)行 _init() 初始化函數(shù), 初始化函數(shù)打印一個(gè)提示信息, 然后調(diào)用主程序的注冊(cè)函數(shù)給結(jié)構(gòu)體重新賦值, 然后調(diào)用結(jié)構(gòu)體的函數(shù)指針, 打印該結(jié)構(gòu)體的值. 這樣就充分的達(dá)到了主程序和動(dòng)態(tài)

12、庫(kù)的函數(shù)相互調(diào)用和指針的相互傳遞.gcc參數(shù) -rdynamic 用來(lái)通知鏈接器將所有符號(hào)添加到動(dòng)態(tài)符號(hào)表中(目的是能夠通過(guò)使用 dlopen 來(lái)實(shí)現(xiàn)向后跟蹤).gcc參數(shù) -fPIC 作用: 當(dāng)使用.so等類的庫(kù)時(shí),當(dāng)遇到多個(gè)可執(zhí)行文件共用這一個(gè)庫(kù)時(shí), 在內(nèi)存中,這個(gè)庫(kù)就不會(huì)被復(fù)制多份,讓每個(gè)可執(zhí)行文件一對(duì)一的使用,而是讓多個(gè)可執(zhí)行文件指向一個(gè)庫(kù)文件,達(dá)到共用. 宗旨:節(jié)省了內(nèi)存空間,提高了空間利用率.linux生成(加載)動(dòng)態(tài)庫(kù)靜態(tài)庫(kù)和加載示例方法動(dòng)態(tài)庫(kù)的生成:1、/*mysum.c*/#include <stdio.h>#include "src.h&qu

13、ot;int sum(int a,int b)return (a+b);2、/*mysum.h*/代碼如下:#ifndef _SRC_H_#define _SRC_H_int sum(int a,int b);#endif 3、/*main.c*/ 代碼如下:#include <stdio.h>extern int sum(int a,int b);/*#include <stdio.h>#include "mysum.h"*/int main()int a,b,c=0;printf("input a and b:n&q

14、uot;);scanf("%d %d",&a,&b);c = sum(a,b);printf("c = %dn",c);return 0; 4、生成動(dòng)態(tài)庫(kù) 代碼如下:gcc -c -fPIC mysum.c mysum.h /生成mysum.o文件gcc -shared -fPIC -o libmysum.so mysum.o /生成動(dòng)態(tài)庫(kù)文件,默認(rèn)的命名方式為lib+名稱.so 5、動(dòng)態(tài)庫(kù)靜態(tài)加載 代碼如下:gcc -o main main.c -L. -lmysum -Wall或gcc -o main main.c -lmysum -Wall 6、執(zhí)行 ./main時(shí)會(huì)報(bào)告錯(cuò)誤,提示無(wú)法加載libmysum.so共享庫(kù)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論