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).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...
随机推荐
- 关于MySQL的一些骚操作——提升正确性,抠点性能
概要 回顾以前写的项目,发现在规范的时候,还是可以做点骚操作的. 假使以后还有新的项目用到了MySQL,那么肯定是要实践一番的. 为了准备,创建测试数据表(建表语句中默认使用utf8mb4以及utf8 ...
- springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig
原文地址:http://blog.csdn.net/yp090416/article/details/78017552 springcloud微服务实战:Eureka+Zuul+Ribbon+Hyst ...
- Lustre 文件系统安装
制作一个本地镜像 reposync configfile: [root@localhost html]# cat lustre-repo.conf [lustre-server] name=lustr ...
- C学习笔记(2)---各类函数
1.函数(function)声明定义: 见例子,不复述:https://www.runoob.com/cprogramming/c-functions.html 2. 函数参数(Parameters“ ...
- IDEA运行单个Java文件
对于某些Java示例可能是只有单个文件,并不是完整的Java工程,那么要如何运行单个Java文件呢,以IDEA为例. 我的环境: IDEA 2017.3.2 jdk 1.8.0.73 操作步骤: 1. ...
- 浅谈JS函数防抖及应用场景
[前言] 在工作中,我们可能碰到这样的问题: 用户在搜索的时候,在不停敲字,如果每敲一个字我们就要调一次接口,接口调用太频繁,给卡住了. 用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每 ...
- Python的运用基础3
1. 简述执行Python程序的两种方式以及他们的优缺点? 交互式(jupyter) 优点:运行一句执行一句 缺点:关闭即消失 ==例如== win10系统cmd窗口 命令行式(Pycharm) 优点 ...
- 201271050130-滕江南-《面向对象程序设计(java)》第十五周学习总结
201271050130-滕江南-<面向对象程序设计(java)>第十五周学习总结 博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.c ...
- 201871010102-常龙龙《面向对象程序设计(java)》第十一周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- python将xml文件数据增强(labelimg)
在处理faster-rcnn和yolo时笔者使用labelimg标注图片 但是我们只截取了大概800张左右的图,这个量级在训练时肯定是不够的,所以我们需要使用数据增强(无非是旋转加噪调量度)来增加我们 ...