LINUX系统中动态链接库的创建与使用(0分)

  • 主题发起人 主题发起人 飘香剑雨
  • 开始时间 开始时间

飘香剑雨

Unregistered / Unconfirmed
GUEST, unregistred user!
LINUX系统中动态链接库的创建与使用
1. Linux 动态链接
Linux 中的应用程序以以下两种方式之一链接到外部函数:要么在构建时与静态库(lib*.a)静态地链接,并且将库代码包含在该应用程序的可执行文件里;要么在运行时与共享库(lib*.so)动态地链接。通过动态链接装入器,将动态库映射进应用程序的可执行内存中。在启动应用程序之前,动态链接装入器将所需的共享目标库映射到应用程序的内存,或者使用系统共享的目标并为应用程序解析所需的外部引用。现在应用程序就可以运行了。
2、LINUX下动态链接库的使用
2.1 重要的dlfcn.h头文件
LINUX下使用动态链接库,源程序需要包含dlfcn.h头文件,此文件定义了调用动态链接库的函数的原型。下面详细说明一下这些函数。
2.1.1 dlerror
原型为: const char *dlerror(void);
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
2.1.2 dlopen
原型为: void *dlopen (const char *filename, int flag);
dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。
filename: 如果名字不以/开头,则非绝对路径名,将按下列先后顺序查找该文件。
(1) 用户环境变量中的LD_LIBRARY值;
(2) 动态链接缓冲文件/etc/ld.so.cache
(3) 目录/lib,/usr/lib
flag表示在什么时候解决未定义的符号(调用)。取值有两个:
1) RTLD_LAZY : 表明在动态链接库的函数代码执行时解决。
2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。
dlopen调用失败时,将返回NULL值,否则返回的是操作句柄。
2.1.3 dlsym : 取函数执行地址
原型为: void *dlsym(void *handle, char *symbol);
dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。由此地址,可以带参数执行相应的函数。
如程序代码: void (*add)(int x,int y);
/* 说明一下要调用的动态函数add */
add=dlsym("xxx.so","add");
/* 打开xxx.so共享库,取add函数地址 */
add(89,369);
/* 带两个参数89和369调用add函数 */
2.1.4 dlclose : 关闭动态链接库
原型为: int dlclose (void *handle);
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
3.dll 示例:小的 C 程序和 dlTest
动态链接装入器示例程序是一个小的 C 程序,该程序被设计用来练习 dl 例程。该程序基于每个人都编写过的一个 C 程序,它将“Hello World”打印到控制台上。最初打印的消息是“HeLlO WoRlD”。该测试程序链接到再次打印该消息的两个函数上:第一次都用大写字符,第二次都用小写字符。
以下是该程序的概要:
1. 定义 dll include 文件 dlfcn.h 和所需的变量。 至少需要这些变量:
o 到共享库文件的句柄
o 指向被映射函数入口点的指针
o 指向错误字符串的指针
2. 打印初始消息,“HeLlO WoRlD”。
3. 使用绝对路径“/home/dlTest/UPPERCASE.so”和选项 RTLD_LAZY,dlopen 打开 UPPERCASE dll 的共享目标文件并返回句柄。
o 选项 RTLD_LAZY 推迟解析 dll 的外部引用,直到 dll 被执行。
o 选项 RTLD_NOW 在 dlopen 返回之前解析所有的外部引用。
4. dlsym 返回入口点 printUPPERCASE 的地址。
5. 调用 printUPPERCASE 并且打印修改过的消息“HELLO WORLD”。
6. dlclose 关闭到 UPPERCASE.so 的句柄,并且从内存中取消 dll 映射。
7. dlopen 使用基于环境变量 LD_LIBRARY_PATH 的相对路径查找共享目标路径,来打开 lowercase dll 的共享目标文件 lowercase.so,并且返回句柄。
8. dlsym 返回入口点 printLowercase 的地址。
9. 调用 printLowercase 并且打印修改过的信息“hello world”。
10. dlclose 关闭到 lowercase.so 的句柄,并且从内存中取消 dll 映射。
注意,每次调用 dlopen、dlsym 或 dlclose 之后,调用 dlerror 以获取最后的错误信息,并且打印该错误信息字符串。以下是 dlTest 的测试运行:
dlTest 2-Original message
HeLlO WoRlD
dlTest 3-Open Library with absolute path return-(null)-
dlTest 4-Find symbol printUPPERCASE return-(null)-
HELLO WORLD
dlTest 5-printUPPERCASE return-(null)-
dlTest 6-Close handle return-(null)-
dlTest 7-Open Library with relative path return-(null)-
dlTest 8-Find symbol printLowercase return-(null)-
hello world
dlTest 9-printLowercase return-(null)-
dlTest 10-Close handle return-(null)-
完整的 dlTest.c、UPPERCASE.c 和 lowercase.c 源代码清单在本文后面的清单里。
4.清单(应用程序和 dll)
dlTest.c:
/*************************************************************/
/* Test Linux Dynamic Function Loading */
/* */
/* void *dlopen(const char *filename, int flag) */
/* Opens dynamic library and return handle */
/* */
/* const char *dlerror(void) */
/* Returns string describing the last error. */
/* */
/* void *dlsym(void *handle, char *symbol) */
/* Return pointer to symbol's load point. */
/* If symbol is undefined, NULL is returned. */
/* */
/* int dlclose (void *handle) */
/* Close the dynamic library handle. */
/* */
/* */
/* */
/*************************************************************/
#include<stdio.h>
#include <stdlib.h>

/* */
/* 1-dll include file and variables */
/* */
#include <dlfcn.h>
void *FunctionLib; /* Handle to shared lib file */
int (*Function)(); /* Pointer to loaded routine */
const char *dlError; /* Pointer to error string */
main( argc, argv )
{
int rc; /* return codes */
char HelloMessage[] = "HeLlO WoRlD/n";

/* */
/* 2-print the original message */
/* */
printf(" dlTest 2-Original message /n");
printf("%s", HelloMessage);
/* */
/* 3-Open Dynamic Loadable Libary with absolute path */
/* */
FunctionLib = dlopen("/home/dlTest/UPPERCASE.so",RTLD_LAZY);
dlError = dlerror();
printf(" dlTest 3-Open Library with absolute path return-%s- /n", dlError);
if( dlError ) exit(1);
/* */
/* 4-Find the first loaded function */
/* */
Function = dlsym( FunctionLib, "printUPPERCASE");
dlError = dlerror();
printf(" dlTest 4-Find symbol printUPPERCASE return-%s- /n", dlError);
if( dlError ) exit(1);
/* */
/* 5-Execute the first loaded function */
/* */
rc = (*Function)( HelloMessage );
printf(" dlTest 5-printUPPERCASE return-%s- /n", dlError);
/* */
/* 6-Close the shared library handle */
/* Note: after the dlclose, "printUPPERCASE" is not loaded */
/* */
rc = dlclose(FunctionLib);
dlError = dlerror();
printf(" dlTest 6-Close handle return-%s-/n",dlError);
if( rc ) exit(1);

/* */
/* 7-Open Dynamic Loadable Libary using LD_LIBRARY path */
/* */
FunctionLib = dlopen("/home/dlTest/lowercase.so",RTLD_LAZY);
dlError = dlerror();
printf(" dlTest 7-Open Library with relative path return-%s- /n", dlError);
if( dlError ) exit(1);
/* */
/* 8-Find the second loaded function */
/* */
Function = dlsym( FunctionLib, "printLowercase");
dlError = dlerror();
printf(" dlTest 8-Find symbol printLowercase return-%s- /n", dlError);
if( dlError ) exit(1);
/* */
/* 8-execute the second loaded function */
/* */
rc = (*Function)( HelloMessage );
printf(" dlTest 9-printLowercase return-%s- /n", dlError);
/* */
/* 10-Close the shared library handle */
/* */
rc = dlclose(FunctionLib);
dlError = dlerror();
printf(" dlTest 10-Close handle return-%s-/n",dlError);
if( rc ) exit(1);
return(0);
}
UPPERCASE.c:
/************************************************/
/* Function to print input string as UPPER case. */
/* Returns 1. */
/*********************************************** */
int printUPPERCASE ( inLine )
char inLine[];
{
char UPstring[256];
char *inptr, *outptr;

inptr = inLine;
outptr = UPstring;
while ( *inptr != '/0' )
*outptr++ = toupper(*inptr++);
*outptr++ = '/0';
printf(UPstring);
return(1);
}
lowercase.c
/********************************************/
/* Function to print input string as lower case. */
/* Returns 2. */
/******************************************* */
int printLowercase( inLine )
char inLine[];
{
char lowstring[256];
char *inptr, *outptr;
inptr = inLine;
outptr = lowstring;
while ( *inptr != '/0' )
*outptr++ = tolower(*inptr++);
*outptr++ = '/0';
printf(lowstring);
return(2);
}
 

Similar threads

后退
顶部