首页 > 系统相关 >linux之dlopen、dlsym和dlclose使用和举例

linux之dlopen、dlsym和dlclose使用和举例

时间:2023-04-25 15:33:48浏览次数:48  
标签:__ include handle 函数 dlsym int linux dlclose hello


 之前用过这三个函数一直没时间整理一下。今天抽时间整理一下。

1、函数简介

dlopen

基本定义

功能:打开一个动态链接库 
  包含头文件: 
  #include <dlfcn.h> 
  函数定义: 
  void * dlopen( const char * pathname, int mode ); 
  函数描述: 
  在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。 
  mode:分为这两种 
  RTLD_LAZY 暂缓决定,等有需要时再解出符号 
  RTLD_NOW 立即决定,返回前解除所有未决定的符号。 
  RTLD_LOCAL 
  RTLD_GLOBAL 允许导出符号 
  RTLD_GROUP 
  RTLD_WORLD 

  返回值: 
  打开错误返回NULL 
  成功,返回库引用 
  编译时候要加入 -ldl (指定dl库) 

dlsym()
 功能:

根据动态链接库操作句柄与符号,返回符号对应的地址。

包含头文件:

#include <dlfcn.h>

函数定义:

void*dlsym(void* handle,const char* symbol)

函数描述:

dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。

handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。

dlclose()

dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

上述都是摘抄,总结为链接的时候需要用到dl库,编译的时候需要加上dlfcn.h头文件。才能保证编译不会报错。

2、生成动态库
hello.c函数原型:
  
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

typedef struct 
{
     const char *module;
     int  (*GetValue)(char *pszVal);
     int   (*PrintfHello)();
} hello_ST_API;


int GetValue(char *pszVal)
{
     int retval = -1;
 
     if (pszVal)
          retval = sprintf(pszVal, "%s", "123456");
      printf("%s, %d, pszVer = %s\n", __FUNCTION__, __LINE__, pszVal);
     return retval;
}

int PrintfHello()
{
     int retval = -1;
 
     printf("%s, %d, hello everyone\n", __FUNCTION__, __LINE__);
     return 0;
}

const hello_ST_API  Hello = 
{
   .module = "hello",
   GetValue,
   PrintfHello,
};

编译的时候用指令:

gcc -shared -o hello.so hello.c

上面的函数是用一个全局结构体hello来指向。在dlsym定义中说不仅可以获取函数的地址,还可以获取全局变量的地址。所以此处是想通过dlsym来获取全局变量的地址。好处自己慢慢体会。

3、dlopen代码

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>

typedef struct {
 const char *module;
 int  (*GetValue)(char *pszVal);
 int   (*PrintfHello)();
} hello_ST_API;


int main(int argc, char **argv)
{
 hello_ST_API *hello;
 int i = 0;
 void *handle;
 char psValue[20] = {0};
 
 handle = dlopen(“库存放的绝对路径,你可以试试相对路径是不行的", RTLD_LAZY);
 if (! handle) {
  printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
  return -1;
 }
 dlerror();

 hello = dlsym(handle, "Hello");
 if (!hello) {
  printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
  return -1;
 }

 if (hello && hello->PrintfHello)
  i = hello->PrintfHello();
  printf("%s, %d, i = %d\n", __FUNCTION__, __LINE__, i);
 if (hello && hello->GetValue)
  i = hello->GetValue(psValue);

 if (hello && hello->module)
  {
   printf("%s, %d, module = %s\n", __FUNCTION__, __LINE__, hello->module);
  }

    dlclose(handle);
    return 0;
}

 

编译指令:gcc -o test hello_dlopen.c -ldl

 

运行./test结果如下。

PrintfHello, 27, hello everyone
main, 36, i = 0
GetValue, 19, pszVer = 123456
main, 42, module = hello

可以看到结果正常出来了。

 

看到没用?dlsym找到全局结构体hello后,可以直接用这个全局结构体指针来使用库里面的函数了,因为我们有时候提供的库不仅仅是一个两个函数的,一般的一个库都会存在多个函数,用这种方式就可以直接使用了。
不然找函数名称的话要写多少个dlsym啊?

 

标签:__,include,handle,函数,dlsym,int,linux,dlclose,hello
From: https://blog.51cto.com/u_16081664/6224148

相关文章

  • linux中修改文件常用vim命令
    linux中修改文件常用vim命令个人博客地址:https://note.raokun.top拥抱ChatGPT,国内访问网站:https://www.playchat.top按键作用含义i在当前字符前插入(记忆:insert)I在光标所在行的行首插入a在当前字符后插入(记忆:afterinsert)A在光标所在行的行尾插入......
  • RHEL8常用命令-Linux就该这么学2
       首先介绍系统内核和Shell终端的关系与作用,然后介绍Bash解释器的4大优势并学习Linux命令的执行方法。经验丰富的运维人员能够通过合理地组合命令,来更精准地满足工作需求,还可以尽可能地降低系统资源消耗。   本章选出常用的数十个Linux命令,它们与系统工作......
  • Linux解压RAR文件
    首先说明1、linux中常常会遇到一些rar结尾的文件包,靠linux本身的命令是无法实现解压rar结尾的文件夹的,需要安装rar的压缩软件才可以。2、要将服务器的账号切换为root账户,否则安装会出错。1、下载linux版本的rar软件访问RARLAB官网下载最新的、适用于自己的linux版本的rar软件......
  • Linux VFS中write系统调用实现原理
    目录用户空间的write函数在内核里面的服务例程为sys_write.1Vfs_write函数实现原理...2 WORD里面的目录复制过来似乎不能直接用。。还是放在这里当主线看吧..用户空间的write函数在内核里面的服务例程为sys_writeroot@syslab~]#grepwrite/usr/include/asm/unistd......
  • 处理Linux 终端中文显示乱码问题
    问题详情:中文命名的文件或者文件夹显示?号或者□,无法正常显示文件名1、查看是否已安装中文字体#查看已安装的中文字体fc-list:lang=zh#查看已安装的中文字体并排序fc-list:lang=zh-cn|sort2、安装字体库yum-yinstallfontconfig3、添加中文字体,建立存储中文......
  • rust交叉编译配置:windows上编译linux可执行程序
    rust交叉编译配置:windows上编译linux可执行程序简述交叉编译大概指在在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码.本次,我们配置的是在windows上编译出在linux上运行的rust可执行程序.我们在安装rust之后,默认会安装跟机器环境搭配的编译相关工具.......
  • xshell 传输文件后,Linux终端显示乱码
    原因:XSHELL与Linux编码设置不一致终端:xshell: 解决方法:设置为一致即可 ......
  • Linux常用技巧(十三)
    1、点亮指定硬盘:定位,磁盘闪灯/opt/MegaRAID/MegaCli/MegaCli64-PdLocate-start-physdrv[E:S]-a0/opt/MegaRAID/MegaCli/MegaCli64-PdLocate-stop-physdrv[E:S]-a02、查看证书过期时间echo|openssls_client-servername${domain}-connect${domain}:4432>/dev/null|......
  • 10 iozone Examples for Disk I/O Performance Measurement on Linux
    https://www.thegeekstuff.com/2011/05/iozone-examples/ Aswediscussedinour Linuxperformancemonitoringintroduction article,measuringIOsubsystemperformanceisveryimportant.Ifsomeoneiscomplainingthatadatabase(oranyapplication)running......
  • Linux安装Tomcat
    1.通过远程链接软件连接上我们的linux服务器,下载linux版本的jdk和tomcat压缩包并上传到我们的服务器中,如下:2.分别进行解压缩:tar-zxv-fjdk-8u371-linux-x64.tar.gz回车tar-zxv-fapache-tomcat-8.5.49.tar.gz回车3.启动防火墙systemctlstartfirewalld,查看防火墙......