共享库的高级特性
来源:互联网 发布:奥林巴斯25mm1.8知乎 编辑:程序博客网 时间:2024/06/01 22:30
库的动态加载
一般用于实现插件功能,可通过调用函数来加载、卸载共享库。可以查找共享库中函数名、变量名所对应的指针。
# include <dlfcn.h>void *dlopen(const char *libfilename, int flags); //打开共享库int dlclose(void *handle); //关闭共享库const char *dlerror(void); //返回错误字符串void *dlsym(void *handle, char *symbol); //查找共享库中的符号
注意:使用共享库的动态加载,在gcc链接时,要加入 -ldl 选项。
dlopen() 打开共享库
void *dlopen(const char *libfilename, int flags);
- void *返回值:成功返回共享库句柄,失败返回NULL
- const char *libfilename:共享库名称
- 名字包含’/’:按照绝对路径或相对路径使用
- 名字不包含’/’:按照连接器默认方式搜索共享库
- int flags:选项
- RTLD_LAZY:不解析共享库中未定义函数符号的内存地址,使用时再解析
- RTLD_NOW:解析共享库库中未定义函数符号的内存地址,可用于调试
注:以上两个选项为必选选项,二选一 - RTLD_GLOBAL:这个共享库中解析的函数符号可以被后面打开的库使用
- RTLD_LOCAL:这个共享库中解析的函数符号不能被后面打开的库使用
注:以上两个选项为共享库的使用范围 - RTLD_NODELETE:不卸载共享库,即使dlclose()后引用计数为0。此时,dlopen()不会重新初始化库中静态变量(glibc2.2可用)
- RTLD_NOLOAD:不加载共享库,作用1:可用与测试共享库是否被加载,如果加载返回共享库句柄,不加载返回NULL。作用2:可再已打开的共享库上添加新的flags。(glibc2.2可用)
- RTLD_DEEPBIND:解析库中符号引用时,先搜索库中的定义,如果库中没有,再搜索全局定义。(这个很有用,可无脑加上,glibc2.3.4可用)
dlclose() 关闭共享库
int dlclose(void *handle);
- int返回值:成功返回0,失败返回非0
- void *handle:共享库句柄
dlerror() 错误原因
const char *dlerror(void);
- const char *返回值:如果dl系列函数出错,可调用dlerror()获取出错原因字符串
dlsym():获取符号的地址
void *dlsym(void *handle, char *symbol);
- void *返回值:成功返回符号的地址,失败返回NULL
- void *handle:共享库句柄
- char *symbol:符号名称(函数名、变量名)
例子
root@jing-VirtualBox:~# lsa.out libt.so main.c t.croot@jing-VirtualBox:~# cat t.c #有点懒,并没有写t.c的头文件。。。# include <stdio.h>void f(){ printf("lib t\n");}root@jing-VirtualBox:~# cat main.c # include <stdio.h># include <dlfcn.h>int main(void){ void *hander = dlopen("./libt.so", RTLD_LAZY); if (hander == NULL) { printf("%s\n", dlerror()); } void (*f)() = dlsym(hander, "f"); f(); //调用函数f dlclose(hander); return 0;}root@jing-VirtualBox:~# gcc main.c -ldlroot@jing-VirtualBox:~# ./a.out lib t
共享库的设计
因库可以动态加载,所以优秀共享库的.h文件,只包含对外可见的接口&变量。这样可以减少开销,防止程序员使用共享库私有的接口导致共享库升级时版本不兼容。
使用static关键字修饰符号,表示符号私有于一个代码快,无法被其他.o文件使用。
链接器版本脚本
作用:确保连接器只导出指定符号。
gcc -shared a.o b.o c.o -o libabc.so -Wl,--version-script,scriptfile.map
-Wl,–version-script,scriptfile.map:指定一个脚本,规定可以导出的符号,脚本如下
VER_1 { global: # 可以被加载的符号 f_a; f_b; f_c; local: *; #*表示除global之外的所有符号};
共享库的初始化函数和终止函数
初始化函数会在共享库加载的时候自动执行,终止函数会在共享库卸载的时候自动执行,代码如下。
void __attribute__ ((constructor)) 初始化函数名(void){ /*初始化代码*/}void __attribute__ ((destructor)) 终止函数名(void){ /*终止代码*/}
注:以上均出自 Linux/UNIX系统编程手册,只选了感觉有用的。
阅读全文
0 0
- 共享库的高级特性
- 类的高级特性
- java的高级特性
- Python的高级特性
- java的高级特性
- CSS3的高级特性
- Redis的高级特性
- python的高级特性
- C++的高级特性
- 类的高级特性
- Java的高级特性
- 共享数据的高级技巧
- 正则表达式的高级特性
- C++函数的高级特性
- 11---java的高级特性
- bean高级特性的学习
- 面向对象的高级特性
- Java的高级特性反射
- Employee Importance问题及解法
- 【资讯】新增两只比特币期货ETF待美国证交会审批
- Ubuntu16:安装KeePass2
- 微信公众号怎么上传图文消息-微信公众号使用教程11
- JAVA EE 7 各技术、组件版本
- 共享库的高级特性
- STM32 MDK 生成 .bin文件
- MediaCodec的介绍及实例
- fore-each操作数组
- HDU 4445(计算几何+暴力)
- MySql全文索引
- 秋招求职记(二)
- python基础--lambda
- sqlserver按'一二三四五'排序(hibernate对中文数字进行排序)