zoukankan      html  css  js  c++  java
  • dlopen动态链接库操作

    void *dlopen(const char *filename, int flag);   //打开一个动态链接库,并返回动态链接库的句柄
    char *dlerror(void);
    void *dlsym(void *handle, const char *symbol);  //根据动态链接库操作句柄与符号,返回符号对应的地址
    int dlclose(void *handle);

    glibc还增加了两个POSIX标准中没有的API:

    • dladdr,从函数指针解析符号名称和所在的文件
    • dlvsym,与dlsym类似,只是多了一个版本字符串参数

    初始化(initializing)和终止化(finalizing)函数

    void _init(void);
    void _fini(void);
    1. 当一个库通过dlopen()动态打开或以共享库的形式打开时,如果_init在该库中存在且被输出出来,则_init函数会被调用。如果一个库通过dlclose()动态关闭或因为没有应用程序引用其符号而被卸载时,_fini函数会在库卸载前被调用
    2. 当使用你自己的_init和_fini函数时,需要注意不要与系统启动文件一起链接。可以使用GCC选项 -nostartfiles 做到这一点
    3. 但是,使用上面的函数或GCC的-nostartfiles选项并不是很好的习惯,因为这可能会产生一些意外的结果。相反,库应该使用attribute函数属性来输出它的构造函数和析构函数
    void __attribute__((constructor)) x_init(void)
    void __attribute__((destructor)) x_fini(void)

    例一:

    //主程序 main.c
    
    //申明结构体
    typedef struct __test {
        int i;
        void (* echo_fun)(struct __test *p);
    }Test;
    
    //供动态库使用的注册函数
    void __register(Test *p) {
        p->i = 1;
        p->echo_fun(p);
    }
    
    int main(void) {
    
        void *handle = NULL;
        char *myso = "./mylib.so";
    
        if((handle = dlopen(myso, RTLD_NOW)) == NULL) {
            printf("dlopen - %sn", dlerror());
            exit(-1);
        }
    
        return 0;
    }
    //动态库 mylib.c
    
    //申明结构体类型
    typedef struct __test {
        int i;
        void (*echo_fun)(struct __test *p);
    }Test;
    
    //申明注册函数原型
    void __register(Test *p);
    
    static void __printf(Test *p) {
        printf("i = %d
    ", p->i);
    }
    
    //动态库申请一个全局变量空间
    //这种 ".成员"的赋值方式为c99标准
    static Test config = {
        .i = 0,
        .echo_fun = __printf,
    };
    
    //加载动态库的自动初始化函数
    void _init(void) {
        printf("init
    ");
        //调用主程序的注册函数
        __register(&config);
    }
    # gcc main.c -ldl -rdynamic
    # gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c

    gcc参数 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪).
    gcc参数 -fPIC 作用: 当使用.so等类的库时,当遇到多个可执行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每个可执行文件一对一的使用,而是让多个可执行文件指向一个库文件,达到共用. 宗旨:节省了内存空间,提高了空间利用率

    例二:

    //主程序 main.c
    
    int main(int argc, char **argv)
    {
        void *handle;
        void (*callfun)();
        char *error;
        handle = dlopen("/root/tmp/hello.so",RTLD_LAZY);  //如果hello.so不是在LD_LIBRARY_PATH所申明
                                                          //的路径中必须使用全路径名
        if(!handle)
        {
            printf("%s 
    ",dlerror());
            exit(1);
        }
        callfun = (void(*)())dlsym(handle,"hello");    //为函数指针赋值
        if(callfun == NULL)
        {
            printf("%s 
    ",dlerror());
            exit(1);
        }
        callfun();                          //调用
        dlclose(handle);
    //动态库 hello.c
    
    void hello(void)
    {
        printf("hello
    ");
    }
    # gcc main.c -ldl
    # gcc -shared -fPIC -o hello.so hello.c

    例三:

    //动态链接库依赖了主程序中的symbol
    
    int day (int a);
    int life(int a)
    {
        return day(a)+8;
    }
    int day(int a)
    {
       printf("this is day function
    ");
       return a+2;
    }
    
    int main(int argc, char **argv) {
       void *handle;
       int (*life)(int a);
       char *error;
       handle = dlopen ("liblife.so", RTLD_LAZY);
       if (!handle) {
           fprintf (stderr, "%s
    ", dlerror());
           exit(1);
       }
       dlerror();    /* Clear any existing error */
       life  = dlsym(handle, "liblife.so");
       if ((error = dlerror()) != NULL)  {
           fprintf (stderr, "%s
    ", error);
           exit(1);
       }
       printf("%d
    ", life(1));
       dlclose(handle);
       return 0;
    }
    # gcc -shared -fpic -o liblife.so life.c
    # gcc -rdynamic main.c -ldl
  • 相关阅读:
    reids 数据库学习
    java 8 学习二(Lambda表达式)
    java 8 学习一(概述)
    update Select 从查询的结果中更新表
    从一段文字中提取出uri信息
    Hadoop3.0磁盘均衡器
    MapReduce 程序mysql JDBC驱动类找不到原因及学习hadoop写入数据到Mysql数据库的方法
    yarn计算一个节点容量及其配置项
    YARN的capacity调度器主要配置分析
    1084 Broken Keyboard (20 分)字符串
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709975.html
Copyright © 2011-2022 走看看