为 Linux 应用程序编写 DLL
<span style="font-family: verdana; line-height: 19px;">为 Linux 应用程序编写 DLL在仅仅只会编写插件的时候为什么要编写整个应用程序?
http://www.ibm.com/i/c.gifhttp://www.ibm.com/developerworks/i/dw.gifhttp://www.ibm.com/i/c.gifhttp://www.ibm.com/i/c.gif文档选项http://www.ibm.com/i/c.gifhttp://www.ibm.com/i/v14/icons/printer.gif打印本页
http://www.ibm.com/i/c.gifhttp://www.ibm.com/i/v14/icons/em.gif将此页作为电子邮件发送
级别: 初级
Allen Wilson (wilsona@us.ibm.com), 电子商务设计师, IBM
2001 年 10 月 01 日
插件和 DLL 通常是用来无须编写整个新应用程序而添加功能的极好方法。在 Linux 中,插件和 DLL 是以动态库形式实现的。电子商务顾问兼设计师 Allen Wilson 介绍了动态库,并且向您演示了如何在某一个应用程序正在运行之后使用动态库来更改该应用程序。Internet 浏览器用户非常熟悉插件的概念。从 Web 上下载插件,通常这些插件为浏览器的音频、视频以及特殊效果提供增强支持。一般来讲,在不更改原有应用程序的情况下,插件为现有应用程序提供新功能。
DLL 是程序函数,它们在设计和构建应用程序时为该程序所知。设计应用程序的主程序时使用程序框架或底板,这些程序框架或底板在运行时选择性地装入所需的 dll,这些 dll 位于磁盘上同主程序分离的一些文件中。这一打包和动态装入提供了灵活的升级、维护、以及许可策略。
随 Linux 一起交付的还有几千条命令和应用程序,它们至少都需要 libc 库函数。如果 libc 函数与每一个应用程序都打包在一起,那么磁盘上将会出现几千个相同函数的副本。Linux 构建这些应用程序,以使用通常所需的系统库的单个系统级副本,而不浪费磁盘空间。Linux 甚至做得更好,每个需要公共系统库函数的进程使用单个的系统级内的副本,一次性将该副本装入到内存并为各进程所共享。
在 Linux 中,插件和 dll 以动态库形式实现。本文的余下部分是在应用程序运行之后使用动态库更改该应用程序的示例。
Linux dll 函数
Linux 提供 4 个库函数( dlopen , dlerror , dlsym 和 dlclose ),一个 include 文件( dlfcn.h )以及两个共享库(静态库 libdl.a 和动态库 libdl.so),以支持动态链接装入器。这些库函数是:
[*]dlopen 将共享目标文件打开并且映射到内存中,并且返回句柄
[*]dlsym返回一个指向被请求入口点的指针
[*]dlerror 返回 NULL 或者一个指向描述最近错误的 ASCII 字符串的指针
[*]dlclose关闭句柄并且取消共享目标文件的映射
动态链接装入器例程 dlopen 需要在文件系统中查找共享目标文件以打开文件并创建句柄。有 4 种方式用以指定文件的位置:
[*]dlopen call 中的绝对文件路径
[*]在 LD_LIBRARY_PATH 环境变量中指定的目录中
[*]在 /etc/ld.so.cache 中指定的库列表之中
[*]先在 /usr/lib 之中,然后在 /lib 之中
http://www.ibm.com/i/v14/rules/blue_rule.gif
http://www.ibm.com/i/c.gifhttp://www.ibm.com/i/c.gif
http://www.ibm.com/i/v14/icons/u_bold.gif
回页首
构建 dlTest
启用运行时动态链接需要三步:
[*]将 dll 编译为位置无关代码
[*]创建 dll 共享目标文件
[*]编译主程序并同 dl 库相链接
编译 UPPERCASE.c 和 lowercase.c 的 gcc 命令包含 -fpic 选项。选项 -fpic 和 -fPIC 导致生成的代码是位置无关的,重建共享目标库需要位置无关。-fPIC 选项产生位置无关的代码,这类代码支持大偏移。用于 UPPERCASE.o 和 lowercase.o 的第二个 gcc 命令,带有 -shared 选项,该选项产生适合于动态链接的共享目标文件 a*.so。
用于编译和执行 dltest 的 ksh 脚本如下:
#!/bin/ksh#Build shared library##set -xclear##Shared library for dlopen absolute path test#if [ -f UPPERCASE.o ]; then rm UPPERCASE.ofigcc-c -fpic UPPERCASE.cif [ -f UPPERCASE.so ]; then rm UPPERCASE.sofigcc -shared -lc-o UPPERCASE.soUPPERCASE.o ##Shared library for dlopen relative path test#export LD_LIBRARY_PATH=`pwd`if [ -f lowercase.o ]; then rm lowercase.ofigcc-c -fpic lowercase.cif [ -f lowercase.so ]; then rm lowercase.sofigcc -shared -lc-o lowercase.solowercase.o##Rebuild test program#if [ -f dlTest ]; then rm dlTestfigcc -o dlTest dlTest.c -ldlecho Current LD_LIBRARY_PATH=$LD_LIBRARY_PATHdlTest
http://www.ibm.com/i/v14/rules/blue_rule.gif
http://www.ibm.com/i/c.gifhttp://www.ibm.com/i/c.gif
http://www.ibm.com/i/v14/icons/u_bold.gif
回页首
清单(应用程序和 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("dlTest2-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("dlTest3-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("dlTest4-Find symbol printUPPERCASE return-%s- \n", dlError);if( dlError ) exit(1);/* *//* 5-Execute the first loaded function *//* */rc = (*Function)( HelloMessage );printf("dlTest5-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("dlTest6-Close handle return-%s-\n",dlError); if( rc ) exit(1);/* *//*7-Open Dynamic Loadable Libary using LD_LIBRARY path *//* */FunctionLib = dlopen("lowercase.so",RTLD_LAZY);dlError = dlerror();printf("dlTest7-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("dlTest8-Find symbol printLowercase return-%s- \n", dlError);if( dlError ) exit(1);/* *//* 8-execute the second loaded function *//* */rc = (*Function)( HelloMessage );printf("dlTest9-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; 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; char *inptr, *outptr; inptr = inLine; outptr = lowstring; while ( *inptr != '' ) *outptr++ = tolower(*inptr++);*outptr++ = ''; printf(lowstring); return(2);}
页:
[1]