c/c :使用dlopen、dlsym、dlclose运行时装载动态库-尊龙官方平台

c/c :使用dlopen、dlsym、dlclose运行时装载动态库

el/2024/3/25 16:58:50

c/c :使用dlopen、dlsym、dlclose运行时装载动态库

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

另外一种则是使用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 count.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 
#include #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;

[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

运行:

[test1280@localhost ~]$ ./main
info:get() return 6

description:

the four functions dlopen(), dlsym(), dlclose(), dlerror() implement the interface to the dynamic linking loader.
void *dlopen(const char *filename, int flag);the function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque "handle" for the  dynamic  library.
void *dlsym(void *handle, const char *symbol);the  function dlsym() takes a "handle" of a dynamic library returned by dlopen() and the null-terminated symbol name, returning the address where that symbol is loaded into memory.
int dlclose(void *handle);the function dlclose() decrements the reference count on the dynamic library handle handle.
if the reference count drops to zero and no other loaded  libraries use symbols in it, then the dynamic library is unloaded.
char *dlerror(void);the function dlerror() returns a human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().

简单点说,就是:

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

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

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

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

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

再多测试下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

其余错误可以自行尝试.

实践是检验真理的唯一标准.

just do it!


http://www.ngui.cc/el/5127132.html

相关文章

c/c :多线程下使用dlopen、dlsym、dlclose装载动态库

c/c:多线程下使用dlopen、dlsym、dlclose装载动态库 当在多线程下dlopen同一个动态库,使用的会是同一个动态库实例还是不同的动态库实例呢? count.h #ifndef _count_h #define _count_h#include int count; pthread_mute…

c/c :多进程使用dlopen、dlsym、dlclose装载动态库

c/c:多进程使用dlopen、dlsym、dlclose装载动态库 曾经我天真地以为,动态库是装载到内存(操作系统)中,如果有多个进程同时dlopen同一个动态库,应当是在os中仅仅有一份动态库实例,当然ÿ…

c/c :pthread_cond_timedwait阻塞失败(立刻超时返回)

c/c:pthread_cond_timedwait阻塞失败(立刻超时返回) 前几天在现网部署软件时,发现一个进程占用cpu非常非常高,仔细探查原因,发现是处理消息时pthread_cond_timedwait阻塞失败,或者说࿰…

c/c :linux时间函数以及基本概念

c/c:linux时间函数以及基本概念 1秒(s)10^3毫秒(ms); 1毫秒(ms)10^3微秒(us); 1微秒(us)10^3纳秒(nsÿ…

c/c :交换两个变量的值可能存在的问题

c/c:交换两个变量的值可能存在的问题 如何交换两个变量的值? 通常我们会借助第三个变量来去完成交换。 假定我们两个变量的类型都是int类型。 #include using namespace std;void swap(int *a, int *b) {if (a null || b null){ …

ftp:基础概念及使用

ftp:基础概念及使用 最近需要做ftp相关的api给业务人员使用,所以了解咯下ftp。 ftp是基于tcp协议,位于第五层(应用层)。 ftp工作建立两条socket链路: 1.控制链路(命令链路)&…

c/c :libcurl smtp 邮件客户端(mua)

c/c:libcurl smtp 邮件客户端(mua) 最近在研究关于邮件的一些东西,需要实现个自己的邮件客户端,也就是类似于foxmail那样的东西。 网上找了下感觉使用libcurl比较便捷靠谱(当然,还有esmtp等库…

other:环比与同比

other:环比与同比 今天看新闻,看到两个熟悉而陌生的词汇:环比、同比。 啥是环比,啥是同比? 环比: 2017年12月销售额130,相比2017年11月销售额100: 环比130/1001.3 环比增长&am…

libcurl:protocol smtps not supported or disabled in libcurl

libcurl:protocol “smtps” not supported or disabled in libcurl 在使用libcurl来作为mua时,开启debug模式,使用smtps协议,在运行时报错: libcurl:protocol “smtps” not supported or disabled in l…

编解码:十六进制编解码

编解码:十六进制编解码 信息有多种表现形式:二进制、十进制、十六进制、字符串… 在计算机中,信息是以二进制的形式来表现。 可以人为定义:0就是假,1就是真,等等。 所谓编解码,是将一种数据…
网站地图