dlopen动态链接库操作
来源:互联网 发布:数据恢复最好的软件 编辑:程序博客网 时间:2024/06/07 06:42
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);
- 当一个库通过dlopen()动态打开或以共享库的形式打开时,如果_init在该库中存在且被输出出来,则_init函数会被调用。如果一个库通过dlclose()动态关闭或因为没有应用程序引用其符号而被卸载时,_fini函数会在库卸载前被调用
- 当使用你自己的_init和_fini函数时,需要注意不要与系统启动文件一起链接。可以使用GCC选项 -nostartfiles 做到这一点
- 但是,使用上面的函数或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\n", p->i);}//动态库申请一个全局变量空间//这种 ".成员"的赋值方式为c99标准static Test config = { .i = 0, .echo_fun = __printf,};//加载动态库的自动初始化函数void _init(void) { printf("init\n"); //调用主程序的注册函数 __register(&config);}
# gcc main.c -ldl -rdynamic# gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c
gcc参数 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪).
gcc参数 -fPIC 作用: 当使用.so等类的库时,当遇到多个可执行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每个可执行文件一对一的使用,而是让多个可执行文件指向一个库文件,达到共用. 宗旨:节省了内存空间,提高了空间利用率
例二:
//主程序 main.cint 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 \n",dlerror()); exit(1); } callfun = (void(*)())dlsym(handle,"hello"); //为函数指针赋值 if(callfun == NULL) { printf("%s \n",dlerror()); exit(1); } callfun(); //调用 dlclose(handle);
//动态库 hello.cvoid hello(void){ printf("hello\n");}
# gcc main.c -ldl# gcc -shared -fPIC -o hello.so hello.c
例三:
//动态链接库依赖了主程序中的symbolint day (int a);int life(int a){ return day(a)+8;}
int day(int a){ printf("this is day function\n"); 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\n", dlerror()); exit(1); } dlerror(); /* Clear any existing error */ life = dlsym(handle, "liblife.so"); if ((error = dlerror()) != NULL) { fprintf (stderr, "%s\n", error); exit(1); } printf("%d\n", life(1)); dlclose(handle); return 0;}
# gcc -shared -fpic -o liblife.so life.c# gcc -rdynamic main.c -ldl
0 0
- dlopen动态链接库操作
- [Linux]使用dlopen、dlsym、dlclose操作访问动态链接库
- dlopen与动态链接库的依赖
- dlopen与动态链接库的依赖
- dlopen dlsym dlclose加载动态链接库
- dlopen与动态链接库的依赖 2
- Android下使用dlopen函数动态调用.so链接库
- Android下使用dlopen函数动态调用.so链接库
- dlsym dlopen打开动态链接库后返回的指针
- LINUX下动态链接库dlopen dlsym dlclose函数使用说明
- LINUX下动态链接库dlopen dlsym dlclose函数使用说明
- 采用dlopen、dlsym、dlclose加载动态链接库【总结】
- 采用dlopen、dlsym、dlclose加载动态链接库【总结】
- 动态链接库dlopen的函数的使用
- dlopen 方式调用 Linux 的动态链接库
- 采用dlopen、dlsym、dlclose加载动态链接库【总结】
- 采用dlopen、dlsym、dlclose加载动态链接库
- 采用dlopen、dlsym、dlclose加载动态链接库
- hdu5148 树形dp,分组背包
- 第十周——面向对象——继承与派生——项目二(2)职员薪水类
- 《控制方法C语言实现》拓展话题讲解系列 第二节
- 【数据结构】实现顺序表(c++)
- poj 3415 后缀数组+单调队列
- dlopen动态链接库操作
- 自动化运维工具---saltstack
- 友盟分享,设置分享平台问题,添加豆瓣等等。
- GDB Manual
- nginx配置详解
- 关于MongoDB你需要知道的几件事
- Leetcode Pascal's Triangle II
- java的数据类型
- 如何解决编译过程中遇到ASN1C相关的问题