• 动态链接函数(dlopen/dlsym/dlclose)使用总结


    一、简介

    动态链接函数操作(显式运行时链接)主要包含头文件dlfcn.h(/usr/include/dlfcn.h),涉及的常用的函数主要有dlopen,dlysm,dlclose。主要作用是从动态库中加载函数到程序中使用,好处是编译的时候不需要链接动态库。

    二、函数原型

    2.1 dlopen

    该函数用于打开动态库并返回句柄。

    void *dlopen (const char *__file, int __mode);
    • 入参1是需要打开的动态库文件

    路径可以是绝对路径,也可以是相对路径,如果参数设置为0,dlopen返回的将是全局符号表的句柄

    • 入参2表示函数符号的解析方式

    入参2有下面几项选择:

    TLD_LAZY表示使用延迟绑定,当函数第一次被用到时才进行绑定。有助于提高加载动态库的速度。

    RTLD_NOW表示当模块被加载时即完成所有函数的绑定工作,如果有任何未定义的符号引用的绑定工作没法完成,那么就返回错误。调试程序的时候可以选择这个选项。

    RTLD_GLOBAL可以和上面两者中任意一个一起使用(或操作),表示将被加载的模块的全局符号合并到进程的全局符号表中,使以后加载的模块可以使用这些符号。

    • 返回值是被加载的模块的句柄

    如果加载使用返回NULL。如果模块被加载过,那么返回的是同一个句柄。

    注意:如果被加载的模块之间有依赖关系,例如模块A依赖模块B,那么需要先加载B再加载A。

    2.2 dlclose

    关闭dlopen的句柄。

    int dlclose (void *__handle);

    入参1 被打开的句斌。会卸载所有已经加载的模块。

    2.3 dlsym

    dlsym是运行时装载的核心函数,通过该函数找到所需要的符号。

    void *dlsym (void * __handle, const char * __name)
    • 入参1是dlopen返回的动态库函数句斌
    • 入参2是所要查找的符号名字,以'\0'为结尾的C字符串。
    • 返回值表示找到的符号的值或者地址。

    找到了对应的符号返回该符号的值,没有找到则返回NULL。如果符号是个变量,那么安徽变量地址;如果这个符号是个常量,返回的该常量的值;如果是个函数,返回函数的地址。

    如果找到的是个常量0,那和未找到返回的NULL,怎么判断是符号还是错误呢,这里使用到dleror函数,如下。

    2.4 dlerror

    用于检查上次调用是否成功。

    char *dlerror (void)

    返回值表示上一次调用是否成功,如果成功,返回值是NULL,如果失败,返回的是char*类型错误信息。

    注意在装入模块时会有符号名冲突(名字相同),先装入的符号优先,这种是装载序列。无论是和什么进程原有符号名冲突还是和后装载的符号冲突,都是采用装载序列。另外还有个依赖序列是指以被dlopen()打开的那个共享对象为根节点,对它所有依赖的共享对象进行广度优先遍历,直到找到符号为止。

    三、举例

    下面是通过查找数学库中的指定函数进行计算操作。

    1. #include
    2. #include
    3. int main(int argc, char **argv) {
    4. void *handle;
    5. double (*cosine)(double);
    6. char *error;
    7. handle = dlopen(argv[1], RTLD_NOW);
    8. if (!handle) {
    9. fprintf(stderr, "%s\n", dlerror());
    10. return 1;
    11. }
    12. cosine = dlsym(handle, "cos");
    13. if ((error = dlerror()) != NULL) {
    14. fprintf(stderr, "%s\n", error);
    15. return 1;
    16. }
    17. printf("%f\n", (*cosine)(2.0));
    18. dlclose(handle);
    19. return 0;
    20. }

    下面是编译和运行结果:

  • 相关阅读:
    前端面试宝典React篇19 React-Router 的实现原理及工作方式分别是什么?
    【vue设计与实现】非原始值的响应式方案 12-代理Set和Map-避免污染原始数据
    HCIP第十八天——链路聚合,VRRP,IPV6
    部署jar包到windows服务器,并自动执行启动脚本
    学3D建模要注意什么问题?入行好几年,踩过的坑后的经验
    Unity之MVC思想(通过普通方法和使用MVC思想完成同一个小案例:掌握MVC简单框架)
    java包的介绍
    基于Python实现并对比线性分类器与非线性分类器
    讲讲如何用IDEA开发java项目——本文来自AI创作助手
    12P4375X042-233C KJ2005X1-BA1 CE3007 EMERSON servo controller
  • 原文地址:https://blog.csdn.net/Ang_ie/article/details/134022000