C語言--使用dlopen、dlsym、dlclose運行時裝載動態庫

一個可執行程序可能與多個動態庫有關聯,通常是在程序運行時將必要的動態庫裝載入進程實體(內存中);

另外一種,則是使用dlopen/dlsym/dlclose來動態地將動態庫裝載到當前進程實體中.

簡單點說,就是:

1.dlopen將指定的動態庫以特定的方式裝載到當前進程實體,並返回一個可操作的句柄,用以後續獲取函數地址等操作;

2.dlsym從指定的(由dlopen的返回值指定)庫中獲得指定的函數(第二個參數爲函數名);

3.dlclose可將關閉卸載動態庫;注意,實際是減掉一個對動態庫的引用(ref),僅當減到0時纔會觸發卸載動態庫的操作;

4.dlerror返回一個字符串用以描述錯誤;

通常的三段式就是:先打開(dlopen),然後獲得需要的函數(dlsym),然後調用函數,最後關閉(dlclose)

示例:

動態庫:
count.h

#ifndef _COUNT_H
#define _COUNT_H
int count;

int get();
void inc();

#endif

count.c

#include "count.h"

int get()
{
    return count;
}

void inc()
{
    count++;
}

編譯動態庫:

[test1280@localhost ~]$ gcc -fPIC -c count.c
[test1280@localhost ~]$ gcc -shared -fPIC -o libcount.so *.o
[test1280@localhost ~]$ ll
total 20
-rw-rw-r--. 1 test1280 test1280   76 Oct 21 04:43 count.c
-rw-rw-r--. 1 test1280 test1280   77 Oct 21 04:42 count.h
-rw-rw-r--. 1 test1280 test1280 1568 Oct 21 04:56 count.o
-rwxrwxr-x. 1 test1280 test1280 7913 Oct 21 04:57 libcount.so

dlopen/dlsym/dlclose使用示例:

#include <stdio.h>
#include <dlfcn.h>

#define NUM 6
#define LIBPATH "/home/test1280/libcount.so"

int main()
{
    void *handler = dlopen(LIBPATH, RTLD_LAZY);
    if (handler == NULL)
    {
        printf("ERROR:%s:dlopen\n", dlerror());
        return -1;
    }

    void (*inc)() = (void (*)())dlsym(handler, "inc");
    if (inc == NULL)
    {
        printf("ERROR:%s:dlsym\n", dlerror());
        return -1;
    }

    int i = 0;
    for (; i < NUM; i++)
        inc();

    int (*get)() = (int (*)())dlsym(handler, "get");
    if (get == NULL)
    {
        printf("ERROR:%s:dlsym\n", dlerror());
        return -1;
    }
    printf("INFO:get() return %d\n", get());

    dlclose(handler);

    return 0;
}

編譯:

[test1280@localhost ~]$ gcc -o main main.c -ldl

注意:
源文件中沒有包含count.h頭文件;
編譯時沒有使用-l指定libcount.so
dlfcn.h是dlopen的頭文件,調用時要加-ldl參數

[test1280@localhost ~]$ ll
total 36
-rw-rw-r--. 1 test1280 test1280   76 Oct 21 04:43 count.c
-rw-rw-r--. 1 test1280 test1280   77 Oct 21 04:42 count.h
-rw-rw-r--. 1 test1280 test1280 1568 Oct 21 04:56 count.o
-rwxrwxr-x. 1 test1280 test1280 7913 Oct 21 04:57 libcount.so
-rwxrwxr-x. 1 test1280 test1280 8761 Oct 21 05:12 main
-rw-rw-r--. 1 test1280 test1280  620 Oct 21 05:11 main.c

再多測試下dlerror:

給出一個不存在的動態庫路徑:
#define LIBPATH "/home/test1280/libcount1.so"

[test1280@localhost ~]$ ./main
ERROR:/home/test1280/libcount1.so: cannot open shared object file: No such file or directory:dlopen

給出不存在的函數名稱:
void (*inc)() = (void (*)())dlsym(handler, "inc_test1280");

[test1280@localhost ~]$ ./main
ERROR:/home/test1280/libcount.so: undefined symbol: inc_test1280:dlsym
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章