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\n",dlerror());
exit(EXIT_FAILURE);
}
    //清楚之前错误
dlerror();
    //获取add函数
func=dlsym(handle,"add");
if((error = dlerror())!=NULL){
fprintf(stderr,"%s\n",error);
exit(EXIT_FAILURE);
}
printf("add: %d\n",func(2,7)); func=dlsym(handle,"sub");
printf("sub: %d\n",func(9,2)); func=dlsym(handle,"mul");
printf("mul: %d\n",func(2,7)); func=dlsym(handle,"div");
printf("div: %d\n",func(8,2)); dlclose(handle);
return 0;
}

binary hacks读数笔记(dlopen、dlsym、dlerror、dlclose)的更多相关文章

  1. binary hacks读数笔记(readelf基本命令)

    一.首先对readelf常用的参数进行简单说明: readelf命令是Linux下的分析ELF文件的命令,这个命令在分析ELF文件格式时非常有用,下面以ELF格式可执行文件test为例详细介绍: 1. ...

  2. binary hacks读数笔记(ld 链接讲解 二)

    这块将介绍一下ld链接命令的具体使用.ld的作用:ld是GNU binutils工具集中的一个,是众多Linkers(链接器)的一种.完成的功能自然也就是链接器的基本功能:把各种目标文件和库文件链接起 ...

  3. binary hacks读数笔记(堆、栈 VMA的分布)

    一.首先看一个简单的程序: #include<stdlib.h> int main() { while(1) { sleep(1000); } return 0; } gcc -stati ...

  4. binary hacks读数笔记(共享库)

    共享库从文件结构上来讲,与共享对象没什么区别.Linux下,共享库就是普通的ELF共享对象. 1.共享库命名: libname.so.x.y.z :其中最前面使用前缀lib,中间是库的名字和后缀&qu ...

  5. binary hacks读数笔记(装载)

    1.地址空间 在linux系统中,每个进程拥有自己独立的虚拟地址空间,这个虚拟地址空间的大小是由计算机硬件决定的,具体地说,是由CPU的位数决定的.比如,32位硬件平台决定的虚拟地址空间大小:0--2 ...

  6. binary hacks读数笔记(ld 链接讲解 一)

    首先我们先看两段代码: a.c extern int shared; int main(){ int a=100; swap(&a,&shared); } b.c int shared ...

  7. binary hacks读数笔记(nm命令)

    nm命令(names):输出包含三个部分:1 符号值.默认显示十六进制,也可以指定: 2 符号类型.小写表示是本地符号,大写表示全局符号(external); 3 符号名称. 例如:nm Simple ...

  8. binary hacks读数笔记(readelf命令)

    可以用readelf命令来查看elf文件内容,跟objdump相比,这个命令更详细. 1. readelf -h SimpleSection.o ELF Header: Magic: 7f 45 4c ...

  9. binary hacks读数笔记(objdump命令)

    一.首先看一下几个常用参数的基本含义: objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它还有其他作用,下面以ELF格式可执行文件test为例详细介绍: 1.objdump -f ...

随机推荐

  1. Java 集合看这一篇就够了

    大家好,这里是<齐姐聊数据结构>系列之大集合. 话不多说,直接上图: Java 集合,也称作容器,主要是由两大接口 (Interface) 派生出来的: Collection 和 Map ...

  2. MeteoInfoLab脚本示例:计算垂直螺旋度

    尝试编写MeteoInfoLab脚本计算垂直螺旋度,结果未经验证. 脚本程序: print 'Open data files...' f_uwnd = addfile('D:/Temp/nc/uwnd ...

  3. 【最大匹配+二分答案】POJ 3057 Evacuation

    题目大意 POJ链接 有一个\(X×Y\)的房间,X代表墙壁,D是门,.代表人.这个房间着火了,人要跑出去,但是每一个时间点只有一个人可以从门出去. 问最后一个人逃出去的最短时间,如果不能逃出去,输出 ...

  4. 方格取数(简单版)+小烈送菜(不知道哪来的题)-----------奇怪的dp增加了!

    一.方格取数: 设有N*N的方格图(N<=20),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0. 某人从图的左上角的A(1,1) 点出发,可以向下行走,也可以向右走,直到到达右下 ...

  5. JavaSE学习笔记02运算符、帮助文档生成与Scanner输入

    1. 运算符 1. 算术运算符:+,-,*,/,%,++,-- //二元运算符 int a = 10; int b = 20; int c = 25; int d = 25; System.out.p ...

  6. JS常用事件的总结

    JS常用事件的总结 outsbumit     表单提交事件 onload     页面加载事件 onclick     鼠标单击某个对象事件 ondblclick     鼠标双击某个对象事件 on ...

  7. Luogu P4247 [清华集训2012]序列操作

    题意 给定一个长度为 \(n\) 的序列 \(a\) 和 \(q\) 次操作,每次操作形如以下三种: I a b c,表示将 \([a,b]\) 内的元素加 \(c\). R a b,表示将 \([a ...

  8. 4G DTU在使用时有哪些注意事项?

    4G DTU是用来帮助工业设备快速连接4G网络的设备.众山物联网研发.生产的LTE660正是这样一款功能强大的4G联网"利器". DTU是英文Data Transfer unit的 ...

  9. NB-IoT的HARQ过程是怎么样的

    NB-IoT的HARQ是一种将前向纠错(Forward Error Correction,FEC)编码和ARQ相结合而形成的技术.HARQ的基本原理是缓存没有正确接收到的数据,并且将重传数据和原始数据 ...

  10. Scala-Mongodb入门之CRUD

    Scala入门之Mongo增删改查 环境jdk1.8,scala2.13 使用sbt管理依赖,在build.sbt中添加依赖: libraryDependencies += "org.mon ...