Linux下c函數dlopen實現加載動態庫so文件代碼舉例

dlopen()是一個強大的庫函數。該函數將打開一個新庫,並把它裝入內存。該函數主要用來加載庫中的符號,這些符號在編譯的時候是不知道的。這種機制使得在系統中添加或者刪除一個模塊時,都不須要從新編譯了。能夠在本身的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定義,並在 dl 庫中實現。它須要兩個參數:一個文件名和一個標誌。文件名就是一個動態庫so文件,標誌指明是否馬上計算庫的依賴性。若是設置爲 RTLD_NOW 的話,則馬上計算;若是設置的是 RTLD_LAZY,則在須要的時候才計算。另外,能夠指定 RTLD_GLOBAL,它使得那些在之後才加載的庫能夠得到其中的符號。當庫被裝入後,能夠把 dlopen() 返回的句柄做爲給 dlsym() 的第一個參數,以得到符號在庫中的地址。使用這個地址,就能夠得到庫中特定函數的指針,而且調用裝載庫中的相應函數。由 www.169it.com 蒐集整理html

   在dlopen()函數以指定模式打開指定的動態鏈接庫文件,並返回一個句柄給調用進程。使用dlclose()來卸載打開的庫。linux

mode是打開方式,其值有多個,不一樣操做系統上實現的功能有所不一樣,在linux下,按功能可分爲三類:函數

1 解析方式測試

RTLD_LAZY:在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變量引用老是當即解析)。spa

RTLD_NOW:須要在dlopen返回前,解析出全部未定義符號,若是解析不出來,在dlopen會返回NULL,錯誤爲:: undefined symbol: xxxx.......操作系統

2 做用範圍,可與解析方式經過「|」組合使用指針

RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫重定位。code

RTLD_LOCAL:與RTLD_GLOBAL做用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。若是沒有指明是RTLD_GLOBAL仍是RTLD_LOCAL,則缺省爲RTLD_LOCAL。htm

3 做用方式進程

RTLD_NODELETE:在dlclose()期間不卸載庫,而且在之後使用dlopen()從新加載庫時不初始化庫中的靜態變量。這個flag不是POSIX-2001標準。

RTLD_NOLOAD:不加載庫。可用於測試庫是否已加載(dlopen()返回NULL說明未加載,不然說明已加載),也可用於改變已加載庫的flag,如:先前加載庫的flag爲RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)後flag將變成RTLD_GLOBAL。這個flag不是POSIX-2001標準。

RTLD_DEEPBIND:在搜索全局符號前先搜索庫內的符號,避免同名符號的衝突。這個flag不是POSIX-2001標準。

 

函數返回值:

   打開錯誤返回NULL

   成功,返回庫引用

   編譯時候要加入 -ldl (指定dl庫)

 

具體代碼舉例以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "stdio.h"
#include
int  main( int  argc, char  *argv[])
{
     char  module_name[1024]={ "./test_module.so" };
     char  *error=NULL;
     void  *module_handle = dlopen(module_name, RTLD_NOW);
     if (module_handle == NULL)
     {
       error = dlerror();
       char  tp[1024] = {0};  
       snprintf(tp, 256,
      "Load module \"%s\" error: %s\n" ,
      module_name, error);    
       printf ( "%s" ,tp);
       return  1;
     } else
     {
         printf ( "Load module[%s] success!\r\n" ,module_name);
     }
     return  1;
}
相關文章
相關標籤/搜索