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);
- 当一个库通过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.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 \n",dlerror());
exit(1);
}
callfun = (void(*)())dlsym(handle,"hello"); //为函数指针赋值
if(callfun == NULL)
{
printf("%s \n",dlerror());
exit(1);
}
callfun(); //调用
dlclose(handle);
//动态库 hello.c
void hello(void)
{
printf("hello\n");
}
# 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\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
dlopen动态链接库操作的更多相关文章
- JNI加载hal的dlopen()相关操作
1.函数集合 #include <dlfcn.h> void *dlopen(const char *filename, int flag); char *dlerror(void); v ...
- LINUX下动态链接库的使用-dlopen dlsym dlclose dlerror(转)
dlopen 基本定义 功能:打开一个动态链接库 包含头文件: #include <dlfcn.h> 函数定义: void * dlopen( const char * pathn ...
- 采用dlopen、dlsym、dlclose加载动态链接库
1.前言 为了使程序方便扩展,具备通用性,可以采用插件形式.采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件.linux提供了加载和处理动态链接库的系统 ...
- LINUX下动态链接库的使用-dlopen dlsym dlclose dlerror
本定义 功能:打开一个动态链接库 包含头文件: #include <dlfcn.h> 函数定义: void * dlopen( const char * pathname, int mod ...
- Linux 动态链接库学习笔记
参考资料: http://www.linuxidc.com/Linux/2012-01/50739.htm http://www.yolinux.com/TUTORIALS/LibraryArchiv ...
- dlopen、dlsym和dlclose的使用
在dlopen()函数以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程.使用dlclose()来卸载打开的库. dlopen: dlopen() The function ...
- Linux与Windows中动态链接库的分析与对比
摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...
- LINUX系统中动态链接库的创建与使用
大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...
- LINUX系统中动态链接库的创建与使用{补充}
大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...
随机推荐
- [视频教程] 包管理器方式安装使用openresty新手上路
OpenResty是一个通过Lua扩展Nginx实现的可伸缩的Web平台,内部集成了大量精良的Lua库.第三方模块以及大多数的依赖项.用于方便地搭建能够处理超高并发.扩展性极高的动态Web应用.Web ...
- Hadoop序列化案例实操
需求 统计每一个手机号耗费的总上行流量.下行流量.总流量. 输入数据: 1 13736230513 192.196.100.1 www.atguigu.com 2481 24681 200 2 138 ...
- Ubuntu 图形界面和终端切换
场景 在使用Ubuntu时,不小心按下了 ctrl+alt+f3,突然进入终端,好慌 解决 Ubuntu保留了纯命令行模式,按下 ctrl+alt+f2-6 可以进入纯命令行界面 之后按下 ctrl+ ...
- Node.js—学习
一.Node.js 1. Hello World var http = require('http'); http.createServer(function(request, response) { ...
- centos7虚拟机端口命令
cat /etc/redhat-release # 查看centos 版本 Centos7端口常见命令 虚拟机新开了5005端口,系统内部是显示开了的,但是外部不能访问端口. 一些需要用到的命令: ...
- Hyper-V与VirtualBox或VMware虚拟机软件冲突的解决方法(VirtualBox只能创建32位虚拟机)
Hyper-V与VirtualBox或VMware虚拟机软件冲突的解决方法 Hyper-V是微软的虚拟化软件,功能类似VirtualBox.VMware,可以用来创建虚拟机. 虚拟化软件都是基于CPU ...
- 访问https问题
访问https问题 package com.yuantiao.smartcardms.tools; import com.alibaba.fastjson.JSONObject; import com ...
- Mybatis的XML映射文件(四)
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...
- CodeForces - 545CWoodcutters
传送门 题目大意:n棵树(10^5),坐标xi,高度hi,把这棵树砍到,可以向右倒[xi,xi+hi]被占, 向左倒[xi-hi,xi]被占,必须要倒的坐标没有被占才能倒,不砍倒就xi被占,问最多砍几 ...
- 震惊!CCF改名为中国沙雕化学学会!!!
震惊!中国沙雕计算机学会要改名中国沙雕化学学会??? Ak元素 据传,CCF,发现了一种新元素,元素符号暂命名为为Ak,中文名称暂未命名,据说是第250号元素. Ak 元素的发现 珂学家在一个叫洛谷的 ...