zoukankan      html  css  js  c++  java
  • binary hacks读数笔记(dlopen、dlsym、dlerror、dlclose)

    1、dlopen是一个强大的库函数。该函数将打开一个动态库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。比如 Apache Web 服务器利用这个函数在运行过程中加载模块,这为它提供了额外的能力。一个配置文件控制了加载模块的过程。这种机制使得在系统中添加或者删除一个模块时,都 不需要重新编译了。 
    可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现。它需要两个参数:一个文件名和一个标志。

    功能:打开一个动态链接库
    包含头文件: 
    #include <dlfcn.h> 
    函数定义: 
    void * dlopen( const char * pathname, int mode ); 
    函数描述: 
    在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。 
    mode:分为这两种 
    RTLD_LAZY 暂缓决定,等有需要时再解出符号 
    RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
    RTLD_GLOBAL 允许导出符号 

    打开错误返回NULL 
    成功,返回被加载模块的句柄。
    编译时候要加入 -ldl (指定dl库) 
    例如 
    gcc test.c -o test -ldl

      当库被装入后,可以把 dlopen() 返回的句柄作为给 dlsym() 的第一个参数,以获得符号在库中的地址。使用这个地址,就可以获得库中特定函数的指针,并且调用装载库中的相应函数。

    2、dlsym
    函数原型
    void* dlsym(void* handle,const char* symbol) 
    该函数在<dlfcn.h>文件中。 
    handle是由dlopen打开动态链接库后返回的句柄,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用

    取动态对象地址:
    #include <dlfcn.h>
    void *dlsym(void *pHandle, char *symbol);
    dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。
    使用这个函数不但可以获取函数地址,也可以获取变量地址。比如,假设在so中
    定义了一个void mytest()函数,那在使用so时先声明一个函数指针:
    void (*pMytest)(),然后使用dlsym函数将函数指针pMytest指向mytest函数,
    pMytest = (void (*)())dlsym(pHandle, "mytest");

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

    4、dlerror
    函数原型: 
    const char *dlerror(void); 
    函数描述: 
    当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

    接下来介绍一个实例来看看这几个函数的具体使用:

    首先:将如下程序编译为动态链接库libcaculate.so,编译参数 gcc -fPIC -shared libcaculate.c  -o libcaculate.so程序如下:

     int add(int a,int b)
     {
             return (a+b);
     }
    
     int sub(int a,int b)
    {
             return (a-b);
     }
    
    int mul(int a,int b)
    {
            return (a*b);
     }
     
     int div(int a,int b)
    {
            return (a/b);
     }

    采用上面生成的libcaculate.so,写个测试程序如下,编译选型:gcc -rdynamic -o dl dl.c -ldl

    #include<stdio.h>
    #include<stdlib.h>
    #include<dlfcn.h>
    //动态库路径
    #define LIB_CACULATE_PATH  "./libcaculate.so"
    
    typedef int (*Func)(int,int);
     
    int main()
    {
            void * handle;
            char * error;
         //定义函数指针 Func func;     //打开动态链接库 handle
    =dlopen(LIB_CACULATE_PATH,RTLD_LAZY); if(!handle){ fprintf(stderr,"%s ",dlerror()); exit(EXIT_FAILURE); }     //清楚之前错误 dlerror();     //获取add函数 func=dlsym(handle,"add"); if((error = dlerror())!=NULL){ fprintf(stderr,"%s ",error); exit(EXIT_FAILURE); } printf("add: %d ",func(2,7)); func=dlsym(handle,"sub"); printf("sub: %d ",func(9,2)); func=dlsym(handle,"mul"); printf("mul: %d ",func(2,7)); func=dlsym(handle,"div"); printf("div: %d ",func(8,2)); dlclose(handle); return 0; }
  • 相关阅读:
    1.第一个java程序
    5.第三章 运算符和基本选择结构
    7.关系运算符
    4.第二章章末总结
    3.计算员工工资
    JAVA并发操作——Thread常见用法(Sleep,yield,后台线程)
    JAVA 对象序列化(一)——Serializable
    JAVA 线程中的异常捕获
    JAVA反射机制实例
    JAVA 对象序列化(二)——Externalizable
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/10649717.html
Copyright © 2011-2022 走看看