linux关于动态链接库的操作dlopen,dlclose,dlsym

linux关于动态链接库的操作dlopen,dlclose,dlsym

#include <dlfcn.h>定义了关于动态链接一些操作,本文归纳了百度百科的内容。


1、 dlopen

  • 功能:以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程
  • 头文件:#include <dlfcn.h>
  • 函数定义:void * dlopen( const char * pathname, int mode);
    • 参数1:pathname,表示动态链接库的路径和名字
    • 参数2: mode,打开的模式,分三种,可用"|"符号组合使用
      • 解析方式TLD_LAZY ,在dlopen返回前,对于动态库中的未定义的符号不执行解析(只对函数引用有效,对于变量引用总是立即解析)。
        RTLD_NOW ,需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx…
      • 作用范围RTLD_GLOBAL ,动态库中定义的符号可被其后打开的其它库解析。
        RTLD_LOCAL ,与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位。如果没有指明是RTLD_GLOBAL还是RTLD_LOCAL,则缺省为RTLD_LOCAL
      • 作用方式RTLD_NODELETE ,在dlclose()期间不卸载库,并且在以后使用dlopen()重新加载库时不初始化库中的静态变量。这个flag不是POSIX-2001标准。
        RTLD_NOLOAD ,不加载库。可用于测试库是否已加载(dlopen()返回NULL说明未加载,否则说明已加载),也可用于改变已加载库的flag,
        如:先前加载库的flag为RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。这个flag不是POSIX-2001标准。
        RTLD_DEEPBIND ,在搜索全局符号前先搜索库内的符号,避免同名符号的冲突。这个flag不是POSIX-2001标准。
    • 返回值:错误返回NULL
      成功返回库引用,一个句柄
      编译时候要加入 -ldl (指定dl库) -rdynamic(通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪)
      例如:gcc test.c -o test -ldl-rdynamic

2、 dlclose

  • 功能:用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
  • 头文件:#include <dlfcn.h>
  • 函数定义:int dlclose (void *handle);
    • 参数1:handle,打开库成功时返回的句柄
    • 返回值:0代表成功 , 非0代表失败

3、 dlsym

  • 功能:根据动态链接库操作句柄与符号,返回符号对应的地址,不但可以获取函数地址,也可以获取变量地址。在使用之前,要知道所调用函数的声明。
  • 头文件:#include <dlfcn.h>
  • 函数定义:void*dlsym(void*handle,constchar*symbol)
    • 参数1:handle,打开库成功时返回的句柄
    • 参数2:symbol,要求获取的函数或全局变量的名称
    • 返回值:void* 指向函数的地址,供调用使用。

4、 dlerror

  • 功能:当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
  • 头文件:#include <dlfcn.h>
  • 函数定义:char *dlerror(void);
    • 返回值:返回值为空,表示上次执行的操作函数执行成功
      返回值不为空表示错误信息

5、代码演示

文件:runlib.c

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define DLL_PATH "./libsd.so"
typedef int (*func)(int, int);
int main(){
    void *dlhandler;
    char *error;
    func func = NULL;
    dlhandler = dlopen(DLL_PATH,RTLD_LAZY);
    if(dlhandler == NULL){
        fprintf(stderr,"%s\n",dlerror());
        exit(-1);
    }
    dlerror();
    func = dlsym(dlhandler,"sumab");
    printf("%d\n",func(1,2));
    dlclose(dlhandler);
    return 0;
}

编译命令:gcc -rdynamic -o runlib runlib.c -ldl

运行:

[teanee@localhost runlib]$ ./runlib

运行结果:3

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值