分享
 
 
 

Linux手机DIY.库文件专题.知识准备

王朝system·作者佚名  2006-11-16
窄屏简体版  字體: |||超大  

Linux手机DIY.库文件专题.知识准备

草木瓜转抄 于 2006-11-9

一、序

软件移植过程中,Linux操作系统的库文件着实令人头疼,这方面资料

也比较少。通过一段时间搜索查询推敲,写点总结吧,也算是有点成果。不过

这篇内容大多都是抄的,这里对原创作者表示深深的敬意~

二、重要提示

为了方便更好的理解本文,提供下面链结。

全系列的文章地址,手机应用开发专栏:http://blog.csdn.net/liwei_cmg

相关的重要成果的下载地址:http://play.younet.com/view.php?tid=24045

三、Linux的库文件格式

[以下内容整理自《创建和使用库》一文,作者不详]

C语言中有一些函数不需要进行编译,也可以在多个文件中使用。

一般来说,有此函数会执行一定的标准任务,如数据库输入/输出操作或

屏幕控制等。可以事先对这些函数进行编译,然后将它们放置在一些特殊的目

标代码文件中,这些目标代码文件就称为库。

库文件中的函数可以通过连接程序与应用程序进行连接。这样就不必在每

次开发程序时都对这些通用的函数进行编译了。

不同类型的应用程序会使用不同的函数库。例如:libdbm库中组包含了对

数据库文件进行访问的dbm函数,需要对数据库进行操作的程序就会与该库进

行连接。数学应用程序使用数学库libm,X-Windows应用程序使用Xlib库,

libX11。另外,所有的程序都将使用标准的C函数库。libc,该库中包含了内

存管理或输入输出操作的基本函数,这些库都存放在/usr/lib这些系统公用

的目录中,系统中的任何用户都可以利用这些库。当然用户也可以建立自己

专用的库函数,供自己或其它指定的人员使用。

库可以有三种使用的形式:静态、共享和动态。静态库的代码在编译时就

已连接到开发人员开发的应用程序中,而共享库只是在程序开始运行时才载入,

在编译时,只是简单地指定需要使用的库函数。动态库则是共享库的另一种变

化形式。动态库也是在程序运行时载入,但与共享库不同的是,使用的库函数

不是在程序运行开始,而是在程序中的语句需要使用该函数时才载入。动态库

可以在程序运行期间释放动态库所占用的内存,腾出空间供其它程序使用。由

于共享库和动态库并没有在程序中包括库函数的内容,只是包含了对库函数的

引用,因此代码的规模比较小。

已经开发的大多数库都采取共享库的方式。ELF格式的可执行文件使得共享

库能够比较容易地实现,当然使用旧的a.out模式也可以实现库的共享。Linux

系统中目前可执行文件的标准格式为ELF格式。

GNU库的使用必须遵守Library GNU Public License(LGPL许可协议)。该

协议与GNU许可协议略有不同,开发人员可以免费使用GNU库进行软件开发,但

必须保证向用户提供所用的库函数的源代码。

系统中可用的库都存放在/usr/lib和/lib目录中。库文件名由前缀lib和

库名以及后缀组成。根据库的类型不同,后缀名也不一样。共享库的后缀名

由.so和版本号组成,静态库的后缀名为.a。采用旧的a.out格式的共享库的

后缀名为.sa。

使用gcc编译器就可以将库与自己开发的程序连接起来,例如:libc.so.5

中包含了标准的输入输出函数,当连接程序进行目标代码连接时会自动搜索该

程序并将其连接到生成的可执行文件中。标准的输入输出库中包含了许多基本

的输入输出函数,如printf函数等。也可以连接其它的一些系统函数库,如数

学库等,但与libc.so.5不同,大部分其它的系统库需要在命令行中显式指定

所用的库名。

在/usr/lib和/lib目录中可以找到绝大多数的共享库。连接时将首先搜索

这两个目录。有一些库也可能存放在特定的目录中,在/etc/ld.conf配置文件

中给出了这些目录的列表。连接程序也会对列出的这些目录进行搜索。在默认

情况下,Linux将首先搜索指定库的共享版本,如果找不到,才会去搜索静态

版本。在对共享库进行更新或安装新库后,必须运行ldconfig命令更新

/etc/ld.conf文件中相应的项(如果使用RPM进行安装,一般会自动进行更新,

不过也不能保证这一点)。

在gcc编译器中引用可搜索到的目录中的库文件时,需要使用-l选项和库

名。在gcc命令行上输入-lm可以在程序中连接标准算术库,-l将首先使用

libname.so进行搜索,这里是libm.so。下面的例子将使用算术库创建bookrecs

程序,请注意这里的-lm选项。

$ gcc main.c io.c -o bookrecs -lm

系统中还有一些其它可用的库,常用的是libncurses.a库,包含了一些简

单的鼠标移动例程。在命令行中使用-lncurses选项引用libncurses.so库。下

面的例子同时调用了数学和光标库。

$ gcc mian.c io.c -o bookrecs -lm -lncurses

在引用其它目录中的库时,需要使用-ldir选项指定该目录。该选项指定

了搜索库函数时其它路径。在下面的例子中,用户在连接时使用了mydir目录

中的myio.so库文件。

$ gcc main.c -o bookrecs -lmydir -lmyio

Linux下文件的类型是不依赖于后缀名的,但一般来讲:

.o 为目标文件,类似于windows中的.obj文件

.so 为共享库文件,用于动态连接,类似于dll文件

.a 为静态库,是多个.o文件合在一起,用于静态连接

.la 为libtool自动生成的一些共享库,可用vi编辑查看,主要记录了一

些配置信息。

四、创建和使用Linux库文件

[以下内容整理自《Linux静态/动态链接库的创建和使用》一文,

http://blog.csdn.net/hcj2002/]

和Windows系统一样Linux也有静态/动态链接库,下面介绍创建和使用

方法:

假设有下面几个文件:

头文件String.h,声明相关函数原形,内容如下:

Strlen.c:函数Strlen的实现,获取给定字符串的长度,内容如下:

Strlnen.c:函数StrNlen的实现,获取给定字符串的长度,如果输入字

符串的长度大于指定的最大长度,则返回最大长度,否者返回字符串的实际

长度,内容如下:

生成静态库:

利用GCC生成对应目标文件:

gcc –c Strlen.c Strnlen.c

如果对应的文件没有错误,gcc会对文件进行编译生成Strlen.o和Strnlen.o

两个目标文件(相当于windows下的obj文件)。然后用ar创建一个名字为libstr.a

的库文件,并把Strlen.o 和Strnlen.o的内容插入到对应的库文件中。相关命

令如下:

ar –rc libstr.a Strlen.o Strnlen.o

命令执行成功以后,对应的静态库libstr.a已经成功生成。

/***********************************

Filename : String.h

Description :

Author : HCJ

Date : 2006-5-7

************************************/

int Strlen(char *pStr);

int StrNlen(char *pStr, unsigned long ulMaxLen);

/**************************************

Filename : get string length

Description :

Author : HCJ

Date : 2006/5/7

**************************************/

#include<stdio.h>

#include<assert.h>

int Strlen(char *pStr)

{

unsigned long ulLength;

assert(NULL != pStr);

ulLength = 0;

while(*pStr++)

{

ulLength++;

}

return ulLength;

}

**********************************************

Fileneme: mystrnlen.c

Description: get input string length,if string large

max length input return max length,

else real length

Author: HCJ

Date : 2006-5-7

**********************************************/

#include<stdio.h>

#include<assert.h>

int StrNlen(char *pStr, unsigned long ulMaxLen)

{

unsigned long ulLength;

assert(NULL != pStr);

if(ulMaxLen <= 0)

{

printf("Wrong Max Length!\n");

return -1;

}

ulLength = 0;

while(*pStr++ && ulLength < ulMaxLen)

{

ulLength++;

}

return ulLength;

}

生成动态链接库:

gcc -fpic -shared -o libstr.so Strlen.c Strnlen.c

-fpic 使输出的对象模块是按照可重定位地址方式生成的。

-shared指定把对应的源文件生成对应的动态链接库文件libstr.so

文件。

对应的链接库已经生成,下面看一下如何使用对应的链接库。

静态库的使用:

假设有下面的文件要使用对应的的静态库:

编译生成对应的目标文件:

gcc -c -I/home/hcj/xxxxxxxx main.c

生成可执行文件:

gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.a

其中-I/home/hcj/xxxxxxxx和-L/home/hcj/xxxxxxxx是通过-I和-L指

定对应的头文件和库文件的路径。libstr.a是对应的静态库的名称。这样

对应的静态库已经编译到对应的可执行程序中。执行对应的可执行文件便

可以对应得函数调用的结果。

/*****************************************

FileName: main.c

Description: test static/dynamic library

Author: HCJ

Date : 2005-5-7

******************************************/

#include<stdio.h>

#include <String.h> //静态库对应函数的头文件

int main(int argc, char* argv[])

{

char str[] = {"hello world"};

unsigned long ulLength = 0;

printf("The string is : %s\n", str);

ulLength = Strlen(str);

printf("The string length is : %d(use Strlen)\n", ulLength);

ulLength = StrNlen(str, 10);

printf("The string length is : %d(use StrNlen)\n", ulLength);

return 0;

}

动态库的分为隐式调用和显式调用两种调用方法:

隐式调用的使用使用方法和静态库的调用差不多,具体方法如下:

gcc -c -I/home/hcj/xxxxxxxx main.c

gcc -o main1 -L/home/hcj/xxxxxxxx main.o libstr.so //这里是*.so

在这种调用方式中,需要维护动态链接库的配置文件/etc/ld.so.conf

来让动态链接库为系统所使用,通常将动态链接库所在目录名追加到动态链

接库配置文件中。否则在执行相关的可执行文件的时候就会出现载入动态链

接库失败的现象。在编译所引用的动态库时,可以在gcc采用 –l或-L选项或

直接引用所需的动态链接库方式进行编译。在Linux里面,可以采用ldd命令

来检查程序依赖共享库。

显式调用:

/*****************************************

FileName: main2.c

Description: test static/dynamic library

Author: HCJ

Date : 2005-5-7

******************************************/

#include<stdio.h>

#include<dlfcn.h>

int main(int argc, char* argv[])

{

//define function pointor

int (*pStrlenFun)(char* pStr); //声明对应的函数的函数指针

int (*pStrnlenFun)(char* pStr, int ulMaxLen);

char str[] = {"hello world"};

unsigned long ulLength = 0;

void *pdlHandle;

char *pszErr;

pdlHandle = dlopen("./libstr.so", RTLD_LAZY); //加载链接库/libstr.so

if(!pdlHandle)

{

printf("Failed load library\n");

}

pszErr = dlerror();

if(pszErr != NULL)

{

printf("%s\n", pszErr);

return 0;

}

//get function from lib

pStrlenFun = dlsym(pdlHandle, "Strlen"); //获取函数的地址

pszErr = dlerror();

if(pszErr != NULL)

{

printf("%s\n", pszErr);

return 0;

}

pStrnlenFun = dlsym(pdlHandle, "StrNlen");

pszErr = dlerror();

if(pszErr != NULL)

{

printf("%s\n", pszErr);

return 0;

}

printf("The string is : %s\n", str);

ulLength = pStrlenFun(str); //调用相关的函数

printf("The string length is : %d(use Strlen)\n", ulLength);

ulLength = pStrnlenFun(str, 10);

printf("The string length is : %d(use StrNlen)\n", ulLength);

dlclose(pdlHandle);

return 0;

}

gcc -o mian2 -ldl main2.c

用gcc编译对应的源文件生成可执行文件,-ldl选项,表示生成的对象模

块需要使用共享库。执行对应得文件同样可以得到正确的结果。

相关函数的说明如下:

(1)dlopen()

第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库。

-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。

-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护。

-目录usr/lib。

-目录/lib。

-当前目录。

第二个参数:指定如何打开共享库。

-RTLD_NOW:将共享库中的所有函数加载到内存

-RTLD_LAZY:会推后共享库中的函数的加载操作,直到调用dlsym()时

方加载某函数

(2)dlsym()

调用dlsym时,利用dlopen()返回的共享库的phandle以及函数名称作为

参数,返回要加载函数的入口地址。

(3)dlerror()

该函数用于检查调用共享库的相关函数出现的错误。

这样我们就用简单的例子说明了在Linux下静态/动态库的创建和使用。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有