美文网首页
6.动态加载

6.动态加载

作者: 陈忠俊 | 来源:发表于2020-03-15 14:58 被阅读0次
    1. 对动态库的加载分为自动加载和动态加载两种
      1.1 动态加载:
      程序的执行期间,需要使用到某个动态库中的文件的时候,可以向动态链接器发出请求,将动态库文件加载到内存中。
      1.2 自动加载:
      程序在开始执行的时候,就将依赖的动态库文件加载到内存,再进行函数的链接

    2. 动态加载

    2.1: dlopen()

    #include<dlfcn.h>
    void *dlopen(const *filename, int flags)
    //功能:将动态库加载到内存
    

    参数:
    - filename: 共享库的路径,如果只给定名字,将按照动态链接器的搜索路径去到指定的共享库去寻找该文件LD_LIBRARY_PATH
    - flags: 加载的方式, 取值如下:

       - RTLD_LAZY: 延迟加载,使用时去加载
       - RTLD_NOW: 立即加载。函数返回时,已经加载到内存
    

    返回值:

    • 成功: 返回动态库加载到内存的地址
    • 失败: NULL,可以使用dlerror(3)函数诊断错误的原因

    注意:

    • 动态链接器的API都需要使用到dl动态库文件,所以连接的时候需要使用-ldl

    2.2: dlclose

    #include<dlfcn.h>
    int dlclose(void *handle);
    

    功能:

    • 关闭动态库,仅仅使动态库的引用计数减一,不一定从内存移除该库文件。只有引用计数=0的时候,才会从内存移除
    • handle: 动态库加载到内存的地址
    • 返回值:
      • 0: 成功
      • 非0: 失败, 使用dlerror(3)判断出错原因
        2.3: dlerror
    #include<dlfcn.h>
    char *dlerror(void)
    

    功能:

    • 获取dlopenAPI的错误信息
    • 返回值: 返回错误原因的首地址
    • NULL: 没有错误

    2.4: dlsym

    #include<dlfcn.h>
    void *dlsym(void *handle, const char *symbol);
    

    功能:从动态库的句柄中找到符号的地址
    参数:

    • handle:动态库加载到内存的地址。dlopen的返回值
    • symble:符号的名字,包括函数的名字,全局变量的名字,静态局部变量的名字
      返回值:
    • 成功:返回符号的地址
    • 失败:NULL,dlerror(3)读取错误的原因

    练习,基于上一节的学习,编译动态链接库libmath.so
    练习一:

    #include<stdio.h>
    #include<dlfcn.h>
    
    int main(int argc, char *argv[]){
        void *handle = dlopen(argv[1], RTLD_NOW);
            if(handle == NULL){
                    printf("Load failed: %s\n", dlerror());
                    return -1;
            }
            if(ff == NULL){
                    printf("Can't find: %s\n", dlerror());
                    return -1;
            }
            printf("Load sucess\n");
            dlclose(handle);
            return 0;
    }
    
    

    测试:

    zhongjun@eclipse:~/linkTest$ gcc dynamic_load.c -ldl -o test
    zhongjun@eclipse:~/linkTest$ ./test
    Load sucess
    zhongjun@eclipse:~/linkTest$ ./test libmath.so
    Load sucess
    zhongjun@eclipse:~/linkTest$ ./test libmath.soaa
    Load failed: libmath.soaa: cannot open shared object file: No such file or directory
    

    练习二:

    #include<stdio.h>
    #include<dlfcn.h>
    typedef int (*func_t)(int, int);
    
    int main(int argc, char *argv[]){
        void *handle = dlopen(argv[1], RTLD_NOW);
            if(handle == NULL){
                    printf("Load failed: %s\n", dlerror());
                    return -1;
            }
            func_t ff = (func_t)dlsym(handle, "add"); #强制转换数据类型
            if(ff == NULL){
                    printf("Can't find: %s\n", dlerror());
                    return -1;
            }
            printf("3 + 4 = %d\n", ff(3, 4)); #通过动态库动态加载的方式调用add函数
            printf("Load sucess\n");
            dlclose(handle);
            return 0;
    }
    

    输出:

    zhongjun@eclipse:~/linkTest$ gcc dynamic_load.c -ldl -o test
    zhongjun@eclipse:~/linkTest$ ./test libmath.so
    3 + 4 = 7
    Load sucess
    

    说明:libmath.so动态库包含了add函数,main函数运行的时候通过dlsym找到了该库文件的地址,并找到了该函数。

    相关文章

      网友评论

          本文标题:6.动态加载

          本文链接:https://www.haomeiwen.com/subject/dosqehtx.html