歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

dlopen()是一個強大的庫函數。該函數將打開一個新庫,並把它裝入內存。該函數主要用來加載庫中的符號,這些符號在編譯的時候是不知道的。這種機制使得在系統中添加或者刪除一個模塊時,都不需要重新編譯了。可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定義,並在 dl 庫中實現。它需要兩個參數:一個文件名和一個標志。文件名就是一個動態庫so文件,標志指明是否立刻計算庫的依賴性。如果設置為 RTLD_NOW 的話,則立刻計算;如果設置的是 RTLD_LAZY,則在需要的時候才計算。另外,可以指定 RTLD_GLOBAL,它使得那些在以後才加載的庫可以獲得其中的符號。當庫被裝入後,可以把 dlopen() 返回的句柄作為給 dlsym() 的第一個參數,以獲得符號在庫中的地址。使用這個地址,就可以獲得庫中特定函數的指針,並且調用裝載庫中的相應函數。

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

mode是打開方式,其值有多個,不同操作系統上實現的功能有所不同,在linux下,按功能可分為三類:

1 解析方式

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

RTLD_NOW:需要在dlopen返回前,解析出所有未定義符號,如果解析不出來,在dlopen會返回NULL,錯誤為:: undefined symbol: xxxx.......

2 作用范圍,可與解析方式通過“|”組合使用

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

RTLD_LOCAL:與RTLD_GLOBAL作用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。如果沒有指明是RTLD_GLOBAL還是RTLD_LOCAL,則缺省為RTLD_LOCAL。

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庫)

具體代碼舉例如下:

#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;

}

Copyright © Linux教程網 All Rights Reserved