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

dlopen:

dlopen()
The function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque "handle" for the dynamic
library. If filename is NULL, then the returned handle is for the main program. If filename contains a slash ("/"), then it is interpreted as a
(relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details)

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

编译时候要加入 -ldl (指定dl库)

mode是打开方式,其值有多个,不同操作系统上实现的功能有所不同,在linux下,按功能可分为三类:
1、解析方式
RTLD_LAZY:在dlopen返回前,对于动态库中的未定义的符号不执行解析(只对函数引用有效,对于变量引用总是立即解析)。
RTLD_NOW: 需要在dlopen返回前,解析出所有未定义符号,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......
2、作用范围,可与解析方式通过“|”组合使用。
RTLD_GLOBAL:动态库中定义的符号可被其后打开的其它库解析。
RTLD_LOCAL: 与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位。如果没有指明是RTLD_GLOBAL还是RTLD_LOCAL,则缺省为RTLD_LOCAL。
3、作用方式
RTLD_NODELETE: 在dlclose()期间不卸载库,并且在以后使用dlopen()重新加载库时不初始化库中的静态变量。这个flag不是POSIX-2001标准。
RTLD_NOLOAD: 不加载库。可用于测试库是否已加载(dlopen()返回NULL说明未加载,否则说明已加载),也可用于改变已加载库的flag,如:先前加载库的flag为RTLD_LOCAL,用dlopen(RTLD_NOLOAD|RTLD_GLOBAL)后flag将变成RTLD_GLOBAL。这个flag不是POSIX-2001标准。
RTLD_DEEPBIND:在搜索全局符号前先搜索库内的符号,避免同名符号的冲突。这个flag不是POSIX-2001标准。
 
dlsym:
 void*dlsym(void* handle,const char* symbol)
函数描述:
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址
handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。
返回值:void* 指向函数的地址,供调用使用。

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

dlerror()当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

示例:

#include <stdio.h>
void hello(void)
{
    printf("hello\n");
}

编译命令:

gcc -shared -o hello.so hello.c
代码#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h> 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();
}
dlerror();
callfun=dlsym(handle,"hello");
if((error=dlerror())!=NULL)
{
printf("%s \n",error);
exit();
}
callfun();
dlclose(handle);
return ;
}

编译命令:

gcc -o hello_dlopen hello_dlopen.c -ldl

执行:./hello_dlopen

从中可以体会到编译时不需要库的好处。另外一种在编译的时候需要动态库的使用方法:

http://www.cnblogs.com/leaven/archive/2010/06/11/1756294.html

示例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啊?

 

参考:

http://www.cnblogs.com/leaven/archive/2011/01/28/1947180.html

 

dlopen、dlsym和dlclose的使用的更多相关文章

  1. 采用dlopen、dlsym、dlclose加载动态链接库【总结】

    摘自http://www.cnblogs.com/Anker/p/3746802.html 采用dlopen.dlsym.dlclose加载动态链接库[总结]   1.前言 为了使程序方便扩展,具备通 ...

  2. dlopen, dlsym今天才刚知道干什么用的,羞死人了

    dlopen, dlsym今天才刚知道干什么用的,羞死人了

  3. 采用dlopen、dlsym、dlclose加载动态链接库【总结】(转)

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

  4. 【转】采用dlopen、dlsym、dlclose加载动态链接库

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

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

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

  6. 采用dlopen、dlsym、dlclose dlopen dlerror加载动态链接库【总结】

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

  7. 采用dlopen、dlsym、dlclose加载动态链接库【总结】【转】

    转自:https://www.cnblogs.com/Anker/p/3746802.html 1.前言 为了使程序方便扩展,具备通用性,可以采用插件形式.采用异步事件驱动模型,保证主程序逻辑不变,将 ...

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

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

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

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

随机推荐

  1. TCP协议中的三次握手和四次挥手(图解)(转载http://blog.csdn.net/whuslei/article/details/6667471)

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源 ...

  2. 制作支持UEFI PC的Server2008 R2系统安装U盘

    下载R2系统 ISO ed2k://|file|cn_windows_server_2008_r2_standard_enterprise_datacenter_and_web_with_sp1_x6 ...

  3. the basic index concept

    Computer Science An Overview _J. Glenn Brookshear _11th Edition Over the years numerous variations o ...

  4. ajax普通弹窗;Bootstrp弹窗

    1.普通弹窗 主页面: <head> <meta http-equiv="Content-Type" content="text/html; chars ...

  5. Solr4+IKAnalyzer的安装配置

    一.下载Solr4.10.2 我们以Windows版本为例,solr-4.10.2.zip是目前最新版本,下载地址: http://www.apache.org/dyn/closer.cgi/luce ...

  6. String 与StringBuffer比较

    package String比较; /* * String 与StringBuffer比较 * String 不可变,一旦赋值,就不能被修改 * StringBuffer可变的字符串. * Strin ...

  7. 玩儿了一下django User authentication

    五一在家,VPN不能链接了,而项目在本地run的过程中,又需要链接公司的SSO server才能login.下雨,不想去公司,又不得不在家做task,只能想办法避开SSO login,以前知道djan ...

  8. Fiddler-005-获取 Cookie 信息

    随着网络安全(例如:登录安全等)要求的不断提升,越来越多的登录应用在登录时添加了验证码登录,而验证码生成算法也在不断的进化,因而对含登录态的自动化测试脚本运行造成了一定程度的困扰,目前解决此种问题的方 ...

  9. windows 访问 ubuntu虚拟机 django服务器 失败

    配置ubuntu配置成桥接,在ubuntu虚拟机中运行django.py开发服务器.windows访问django失败. 虚拟机运行: python manage.py runserver 0.0.0 ...

  10. ie下的onscroll和onresize的优化

    ie下的scroll和resize的优化 1.onscroll function scrollEvent(){ //do something... console.log('do something. ...