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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章