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);
  1. 当一个库通过dlopen()动态打开或以共享库的形式打开时,如果_init在该库中存在且被输出出来,则_init函数会被调用。如果一个库通过dlclose()动态关闭或因为没有应用程序引用其符号而被卸载时,_fini函数会在库卸载前被调用
  2. 当使用你自己的_init和_fini函数时,需要注意不要与系统启动文件一起链接。可以使用GCC选项 -nostartfiles 做到这一点
  3. 但是,使用上面的函数或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动态链接库操作的更多相关文章

  1. JNI加载hal的dlopen()相关操作

    1.函数集合 #include <dlfcn.h> void *dlopen(const char *filename, int flag); char *dlerror(void); v ...

  2. LINUX下动态链接库的使用-dlopen dlsym dlclose dlerror(转)

    dlopen 基本定义 功能:打开一个动态链接库  包含头文件:  #include <dlfcn.h>  函数定义:  void * dlopen( const char * pathn ...

  3. 采用dlopen、dlsym、dlclose加载动态链接库

    1.前言 为了使程序方便扩展,具备通用性,可以采用插件形式.采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件.linux提供了加载和处理动态链接库的系统 ...

  4. LINUX下动态链接库的使用-dlopen dlsym dlclose dlerror

    本定义 功能:打开一个动态链接库 包含头文件: #include <dlfcn.h> 函数定义: void * dlopen( const char * pathname, int mod ...

  5. Linux 动态链接库学习笔记

    参考资料: http://www.linuxidc.com/Linux/2012-01/50739.htm http://www.yolinux.com/TUTORIALS/LibraryArchiv ...

  6. dlopen、dlsym和dlclose的使用

    在dlopen()函数以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程.使用dlclose()来卸载打开的库. dlopen: dlopen() The function ...

  7. Linux与Windows中动态链接库的分析与对比

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  8. LINUX系统中动态链接库的创建与使用

    大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...

  9. LINUX系统中动态链接库的创建与使用{补充}

    大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library).这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部 ...

随机推荐

  1. [b0001] 伪分布式 hadoop 2.6.4

    说明: 任务:搭建Hadoop伪分布式版本. 目的:快速搭建一个学习环境,跳过这一环境,快速进入状态,使用Hadoop一些组件做些任务 没有选择2.7,觉得bug比较多,不稳定. 选择伪分布式简单快速 ...

  2. [PHP] 现代化PHP之路:composer的镜像站设置

    1. 当使用composer安装一些类库的时候,默认的镜像站是官方的packagist.org,因为国内的网络环境原因,速度有时候会很慢 2. packagist的中国镜像站有 packagist.p ...

  3. STL关联容器的基本操作

    关联容器 map,set map map是一种关联式容器包含 键/值 key/value 相当于python中的字典不允许有重复的keymap 无重复,有序 Map是STL的一个关联容器,它提供一对一 ...

  4. itest(爱测试) 4.1.5 发布,开源BUG 跟踪管理 & 敏捷测试管理软件

    v4.1.5下载地址 :itest下载 itest 简介:查看简介 itest 开源敏捷测试管理,testOps 践行者.可按测试包分配测试用例执行,也可建测试迭代(含任务,测试包,BUG)来组织测试 ...

  5. mysql里字符集的配置

    [client]default-character-set=utf8[mysqld]character-set-server = utf8[mysql]default-character-set=ut ...

  6. 标签中href="javascript:;"表示什么意思?

    1.标签的 href 属性用于指定超链接目标的 URL,href 属性的值可以是任何有效文档的相对或绝对 URL,包括片段标识符和 JavaScript 代码段. 2.javascript: 是一个伪 ...

  7. lua 5 流程控制 if

    条件判断中,0 表示 true,只有 nil 才是 false if(0) then -- 可以没有括号 print("0 为 true") elseif 1 then print ...

  8. SpringMVC环境搭建(二)

    一.基于XML 1. 创建Maven Project,选择war,修改pom.xml SpringMVC是依赖于Spring的,需要导入核心包. <properties> <!-- ...

  9. luoguP2824 [HEOI2016/TJOI2016]排序(二分答案做法)

    题意 这题的思路实在巧妙. 首先我们肯定无法对区间进行sort,那么考虑如何使得sort简化. 问:如果给的序列是一个0-1序列,让你区间排序,那么怎么做? 答:建一颗线段树维护sum,求出当前区间中 ...

  10. Python process (进程)

    进程 (process) 进程是对各种资源管理的集合,包含对各种资源的调用.内存的管理.网络接口的调用 进程要操作 CPU 必须先启动一个线程,启动一个进程的时候会自动创建一个线程,进程里的第一个线程 ...