快速业务通道

Linux 操作系统动态库剖析

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-05-09
句柄和对象引用了.它完全是按引用来计数的,同一个共享对象的多个用户相互间不会发生冲突(只要还有一个用户在使用它,它就会待在内存中).任何通过已关闭的对象的 dlsym 解析的符号都将不再可用.

char *dlclose( void *handle );

动态加载示例

了解了 API 之后,下面让我们来看一看 DL API 的例子.在这个应用程序中,您主要实现了一个 shell,它允许操作员来指定库、函数和参数.换句话说,也就是用户能够指定一个库并调用该库(先前未链接于该应用程序的)内的任意一个函数.使用 DL API 来解析该库中的函数,然后使用用户定义的参数(用来发送结果)来调用它.清单 2 展示了完整的应用程序.

清单 2. 使用 DL API 的 Shell

#include <stdio.h>
#include <dlfcn.h>
#include <string.h>

#define MAX_STRING 80


void invoke_method( char *lib, char *method, float argument )
{
void *dl_handle;
float (*func)(float);
char *error;

/* Open the shared object */
dl_handle = dlopen( lib, RTLD_LAZY );
if (!dl_handle) {
printf( "!!! %sn", dlerror() );
return;
}

/* Resolve the symbol (method) from the object */
func = dlsym( dl_handle, method );
error = dlerror();
if (error != NULL) {
printf( "!!! %sn", error );
return;
}

/* Call the resolved method and print the result */
printf(" %fn", (*func)(argument) );

/* Close the object */
dlclose( dl_handle );

return;
}


int main( int argc, char *argv[] )
{
char line[MAX_STRING 1];
char lib[MAX_STRING 1];
char method[MAX_STRING 1];
float argument;

while (1) {

printf("> ");

line[0]=0;
fgets( line, MAX_STRING, stdin);

if (!strncmp(line, "bye", 3)) break;

sscanf( line, "%s %s %f", lib, method, &argument);

invoke_method( lib, method, argument );

}

}

要构建这个应用程序,需要通过 GNU Compiler Collection(GCC)使用如下的编译行.选项 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪).-ldl 表明一定要将 dllib 链接于该程序.

gcc -rdynamic -o dl dl.c -ldl

再回到 清单 2,main 函数仅充当解释器,解析来自输入行的三个参数(库名、函数名和浮点参数).如果出现 bye 的话,应用程序就会退出.否则的话,这三个参数就会传递给使用 DL API 的 invoke_method 函数.

调用 dlopen 来访问目标文件.如果返回 NULL 句柄,表示无法找到对象,过程结束.否则的话,将会得到对象的一个句柄,可以进一步询问对象.然后使用 dlsym API 函数,尝试解析新打开的对象文件中的符号.您将会得到一个有效的指向该符号的指针,或者是得到一个 NULL 并返回一个错误.

在 ELF 对象中解析了符号后,下一步就只需要调用函数.要注意一下这个代码和前面讨论的动态链接的差别.在这个例子中,您强行将目标文件中的符号地址用作函数指针,然后调用它.而在前面的例子是将对象名作为函数,由动态链接器来确保符号指向正确的位置.虽然动态链接器能够为您做所有麻烦的工作,但这个方法会让您构建出极其动态的应用程序,它们可以再运行时被扩展.

调用 ELF 对象中的目标函数后,通过调用 dlclose 来关闭对它的访问.

清单 3 展示了一个如何使用这个测试程序的例子.在这个例子中,编译程序而后执行它.接着调用了 math 库(libm.so)中的几个函数.完成演示后,程序现在能够用动态加载来调用共享对象(库)中的任意函数了.这是一个很强大的功能,通过它还能够给程

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号