Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6157
  • 博文数量: 3
  • 博客积分: 87
  • 博客等级: 民兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-28 20:44
文章分类
文章存档

2012年(3)

我的朋友
最近访客

分类: LINUX

2012-06-03 23:30:16

    动态连接库的加载有两种形式:一种是在启动时由ld.so进行加载,另一种是在程序执行过程中通过Linux提供的动态链接库加载接口进行加载。

如果应用程序需要加载libfoo.so(注意,名字必须以lib开始), 那么按照第一种方式,我们需要将libfoo.so拷贝到/usr/lib文件夹下,在编译的时候加入-lfoo即可。如果libfoo.so不在/usr/lib文件夹下,则需要编辑/etc/ld.so.conf文件,加入库文件所在目录的路径,然后运行ldconfig命令。

按照第二种方式,可执行程序调用Linux动态加载接口将动态链接库加载到自己的地址空间,并且解析动态链接库中的符号。

与之相关的函数有三个,第一个函数用于加载动态库。


点击(此处)折叠或打开

  1. void *dlopen(const char *pathname, int mode);

参数pathname是需要加载的库的路径名,mode有三个可选值:RTLD_LAZY表示未定义的符号是来自动态链接库的代码;RTLD_NOW表示要在dlopen函数返回之前确定所有未定义的符号,如果没有完成,则执行失败。RTLD_GLOBAL则表示动态链接库中定义的外部符号可以被随后加载的库使用。如果执行成功,将返回动态链接库的一个句柄。

动态链接库加载完成后,可以调用dlsym函数获取库中的函数以及定义的符号。


点击(此处)折叠或打开

  1. void *dlsym(void *handle, char *symbol);

如果找不到symbol,则返回NULL

当不需要对动态连接库使用的时候,可以调用dlclose将打开的动态链接库与当前进程断开。只有当动态链接库的引用为0的时候,才会将其卸载。


点击(此处)折叠或打开

  1. int *dlcolse(void *handle);

 另外还有一个比较使用的函数就是dlerror(), 这个函数可以帮助我们打印上次调用dlopen, dlsym的出错信息。


点击(此处)折叠或打开

  1. char *dlerror(void);

实例:

foo.cpp:


点击(此处)折叠或打开

  1. #include<stdio.h>
  2. using namespace std;

  3. extern "C"
  4. int func()
  5. {
  6.     printf("This is in foo's func function\n");
  7.     return 0;
  8. }
    dso.cpp:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <dlfcn.h>
  3. using namespace std;

  4. typedef int (*f)();

  5. int main()
  6. {
  7.     void *lSoHandler, *lFuncHandler;
  8.     lSoHandler = dlopen("./foo.o", RTLD_LAZY);
  9.     if(NULL != lSoHandler)
  10.     {
  11.         lFuncHandler = dlsym(lSoHandler, "func");
  12.         if(NULL != lFuncHandler)
  13.         {
  14.             ((f)lFuncHandler)();
  15.         }
  16.         else
  17.         {
  18.             printf("%s\n", dlerror());
  19.         }
  20.         dlclose(lSoHandler);
  21.     }
  22.     else
  23.     {
  24.         printf("%s\n", dlerror());
  25.     }
  26.     
  27.     return 0;
  28. }

编译及运行的命令:

点击(此处)折叠或打开

  1. gcc -shared -nostartfiles -o foo.o foo.cpp

  2. gcc -rdynamic -o dso dso.cpp -ldl -lstdc++

  3. ./dso
    需要注意的一点:要在foo.cpp中加入extern "C", 因为dlsym是C接口,而生成动态库的是C++程序,是C++接口,默认定义了_cplusplus这个宏,于是编译器会按照C++的规则去生成函数名。因此so文件中包含的接口应被声明按C规则编译,否则dlsym会因匹配不到函数名而报错。

阅读(1165) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

Aquester2012-06-06 09:24:41

BigBen_PigBear: 谢谢啦~小弟也是刚刚入门,有很多选项不是很清楚,多谢分享。.....
呵呵,一起学习

BigBen_PigBear2012-06-05 22:00:01

Aquester: 赞,总结得非常好,另外分享一个:可执行的DSO,请参见博文:http://blog.chinaunix.net/uid-20682147-id-351108.html.....
谢谢啦~小弟也是刚刚入门,有很多选项不是很清楚,多谢分享。

Aquester2012-06-04 09:35:40

赞,总结得非常好,另外分享一个:可执行的DSO,请参见博文:http://blog.chinaunix.net/uid-20682147-id-351108.html