C语言:动态库加载



路由器网络操作系统,是一个多进程、多线程的系统,一般由根进程(监控或守护进程)、系统管理进程和N个业务进程组成。其中,根进程与系统管理进程必须存在,用于加载系统中的基础组件,而业务进程的加载与否比较灵活,由配置文件确定,完全可以根据实际需要新增或裁减。
一个业务进程,通常是一个公共的容器进程文件,在被系统管理进程拉起(fork+execv)之后,根据不同的业务配置文件,通过dl库打开不同的动态库的方法,加载相应的业务组件。也就是说,不管系统中有多少业务进程,容器进程文件只有一个。而业务的多样性,通过配置文件+组件动态库提供。容器进程文件比较小,一般仅初始化一些基本模块(如系统时间、信号处理、进程全局数据区、内存管理、TRACE/LOG,共享内存等到),加载基础组件(如组件管理代理、调试终端代理等)。


下面将介绍动态库加载的基本接口函数。

动态库加载的基本接口:

 

1、 dlopen
函数定义:void *dlopen(const char *filename, int mode);
函数功能:指定模式打开一个动态链接库,并返回动态库的句柄handle。
函数描述:
filename指动态库所在的文件路径名,如果filename为NULL,返回主程序handle;
mode用于标识打开方式,不同操作系统上实现的功能有所不同。在Linux系统下,常用的打开方式有以下两类:
1) 解析方式
 RTLD_LAZY:在dlopen返回前,对于动态库中的未定义的符号不执行解析(只对函数引用有效,对于变量引用总是立即解析);
 RTLD_NOW:需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为: undefined symbol: xxx...
2) 作用范围,可与解析方式通过 按位或“|” 组合使用
 RTLD_GLOBAL:动态库中定义的符号可被其后打开的其它库解析;
 RTLD_LOCAL: 与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位。如果未指定RTLD_GLOBAL,则缺省为RTLD_LOCAL。
除此之外,还有RTLD_NODELETE、RTLD_NOLOAD (since glibc 2.2) 、RTLD_DEEPBIND (since glibc 2.3.4) ,当然,这些mode不是POSIX.1-2001标准,不建议使用。

返回值:
 失败,返回NULL,可通过dlerror()获取具体的错误信息;
 成功,返回动态链接库操作句柄handle。

 

2、 dlsym
函数定义:void *dlsym(void *handle, const char *symbol);
函数功能:根据动态链接库操作句柄与符号,返回符号对应的地址。
函数描述:
根据动态链接库的操作句柄(即dlopen的返回值handle)与符号(symbol,即函数名或全局变量名),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle:由dlopen打开动态链接库后返回的handle指针。若handle传入NULL,dlsym将查找进程中已加载指定符号的地址;
symbol:要求获取的函数或全局变量的名称字符串。
返回值:
 失败,返回NULL,可通过dlerror()获取具体的错误信息;
 成功,返回symbol 的地址,可以直接使用。

 

3、 dlclose
函数定义:int dlclose (void *handle);
函数功能:根据动态链接库操作句柄,卸载动态库。
函数描述:
用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

 

4、 dlerror
函数定义:char *dlerror(void);
函数功能:获取最后一次dlopen/dlsym/dlclose操作的产生的错误信息。
函数描述:
该函数主要用于调试,它返回一个可读的错误信息,由上一次调用dlopen/dlsym/dlclose失败时产生;若之前未发生dlopen/dlsym/dlclose的调用错误,则返回NULL。

 

注意点:
1、 使用dl库的接口函数,需要在源文件中 #include <dlfcn.h>,否则,会报以下编译warning:
implicit declaration of function ‘dlopen’     ---编译warning
implicit declaration of function ‘dlsym'
implicit declaration of function ‘dlclose'
implicit declaration of function ‘dlerror'


2、在编译生成进程文件时,加入链接选项 –ldl。否则,会报以下链接error:
undefined reference to `dlopen'               ---链接error
undefined reference to `dlsym'
undefined reference to ` dlclose'
undefined reference to `dlerror'


3、 通过dlopen()打开动态库(.so)文件,可以用绝对路径,也可以用相对路径。但是如果用相对路径打开动态库文件,则在gdb调试时,可能会找不到动态库中的符号;

    当然,可以通过 LD_LIBRARY_PATH 设置查找共享库(动态链接库)时除了默认路径(/lib, /usr/lib)之外的其他路径,这样,dlopen动态库so文件时不需要带路径。不过,作为过来人,个人推荐用绝对路径打开动态库。


4、 更多详细信息,通过下Linux环境下 man dlopen查看。

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值