C语言--使用dlopen、dlsym、dlclose运行时装载动态库

本文介绍了一个可执行程序如何与多个动态库关联,并详细解释了dlopen、dlsym和dlclose这三个函数的作用及使用方法。通过示例展示了如何在不直接链接动态库的情况下,利用这些函数动态加载和调用动态库中的函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个可执行程序可能与多个动态库有关联,通常是在程序运行时将必要的动态库装载入进程实体(内存中);

另外一种,则是使用dlopen/dlsym/dlclose来动态地将动态库装载到当前进程实体中.

简单点说,就是:

1.dlopen将指定的动态库以特定的方式装载到当前进程实体,并返回一个可操作的句柄,用以后续获取函数地址等操作;

2.dlsym从指定的(由dlopen的返回值指定)库中获得指定的函数(第二个参数为函数名);

3.dlclose可将关闭卸载动态库;注意,实际是减掉一个对动态库的引用(ref),仅当减到0时才会触发卸载动态库的操作;

4.dlerror返回一个字符串用以描述错误;

通常的三段式就是:先打开(dlopen),然后获得需要的函数(dlsym),然后调用函数,最后关闭(dlclose)

ps:
每个可执行模块(包括可执行文件和动态链接库)都有自己的数据段用来存放自己的全局变量。
一个进程中所有的可执行模块都在同一个平坦的内存上,操作系统负责为模块分配内存起始地址。
不同的静态变量位于从这个区段的固定位置(可能是起始处或中间的某个位置)偏移不同字节数的地址,在编译时就写死在生成的原生代码中。

示例:

动态库:
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

造夢先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值