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. DevOps 工程师成长日记系列四:打包

    原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-4-packag ...

  2. 怎么更改當前的USERENV('LANG')返回值

    [php] SQL> ALTER SESSION SET NLS_LANGUAGE='AMERICAN'; Session altered. SQL> select USERENV('LA ...

  3. centos7中python3.6报错ModuleNotFoundError: No module named '_ssl' 或者 Max retries exceeded with url: / (Caused by SSLError("Can't connect to HTTPS URL because the SSL module is not available.",))

    如果在运行爬虫时报此错:requests.exceptions.SSLError: HTTPSConnectionPool(host='www.baidu.com', port=443): Max r ...

  4. SQL常用增删改查语句--来源于网络

    1.1[插入单行]insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values ('开心朋朋' ...

  5. VSCode 如何同步设置

    微软新推出的 VSCode 是一款开源.轻量.良心的开发工具,一经问世,迅速受到全球广泛开发者的好评与青睐,威风之下有干掉 Sublime Text 的趋势.然而有不少 VSCode 使用者吐槽其不能 ...

  6. CentOS7设置开机自启动方式

    方式一: # 在/etc/rc.d/rc.local文件中追加启动命令,该文件追加后,会随着机器自动后,自动运行文件中的命令 # vim /etc/rc.d/rc.local # 权限问题:在cent ...

  7. 05webpack-webpack-dev-server时时跟新-第2种方式

    <!--14 第一种方式 自动打开浏览器 端口号 指定托管的跟目录 启动热刷新 这种是在webpack.json中去配置的 直接在package中 写 将“script”:{ "dev ...

  8. 【CSP-SJX 2019】T4 散步

    Description 传送门 Solution 算法1 32pts 枚举每个时刻,并枚举所有发生的时间,暴力进行更新.发现最多只需要枚举到第 \(L\)个时刻,因为是一个环,所以最多到第L个时刻,所 ...

  9. JDOJ3007 铺地板I

    JDOJ3007 铺地板I https://neooj.com/oldoj/problem.php?id=3007 题目描述 有一个大小是 2 x N(1 <= N <= 105)的网格, ...

  10. pointcnn

    这篇论文先举例子解释了为什么卷积无法直接应用在点云数据上. 如图1, 传统的卷积是作用在2维图像数据上.图像中每个像素的顺序是固定的,也就是说数据是结构化存储的.直接使用conv2d就能从这种潜在的空 ...