linux 清理共享函数,linux共享库

linux环境下,库文件包含静态函数库和动态函数库两种:

静态函数库:

这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。

动态函数库:

这类库的名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减小应用程序的体积。

在开发过程中引入库的作用主要包括:

1.函数模块的功能相同,实现代码也相同,通过对它们进行封装为库,方便模块之间的调用,避免代码重复。

2.封装另外一个目的是针对接口编程,对实现代码进行保密,利于代码保护和代码升级。

第一节:静态函数库

在linux中,静态函数库有固定的命名规则:lib+类库名称+.a。

把函数打包成.a静态库包括下面几个步骤:

1.程序实例:

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

FileName : myAddLib.h

FileFunc : 定义头文件

Version : V0.1

Author : Sunrier

Date : 2012-04-28

Descp : Linux下实现静态库

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

#ifndef _MYADDLIB_H_

#define _MYADDLIB_H_

#ifdef __cplusplus

extern "C" {

#endif

int add(int ,int );

#ifdef __cplusplus

}

#endif

#endif

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

FileName : myAddLib.c

FileFunc : 定义静态库实现文件

Version : V0.1

Author : Sunrier

Date : 2012-04-28

Descp : Linux下实现静态库

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

#include

int add(int iArg1,int iArg2)

{

printf("iArg1= %d , iAgr2= %d \n",iArg1,iArg2);

return (iArg1+iArg2);

}

2.制作静态库文件

1.编译并生成目标文件:gcc -c myAddLib.c -o myAddLib.o

2.生成归档文件:ar -rc libmyAddlib.a myAddLib.o

gcc -o myAddLib.o -c myAddLib.c

把源程序文件编译成*.o。-c :只编译并生成目标文件。

ar -rc libmyAddLib.a myAddLib.o

执行完后会生成一个libmyAddLib.a 文件

-c create的意思

-r replace的意思,表示当插入的模块名已经在库中存在,则替换同名的模块.如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块.默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。

3.使用静态库文件

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

FileName : testAddLib.c

FileFunc : 测试静态库文件

Version : V0.1

Author : Sunrier

Date : 2012-04-28

Descp : Linux下实现静态库

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

#include

#include "myAddLib.h"

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

{

int iNumber1,iNumber2,iSum = 0;

iNumber1 = 10;

iNumber2 = 20;

iSum = add(iNumber1,iNumber2);

printf("iSum=%d\n".iSum);

printf("Hello Sunrier!\n");

return 0;

}

编译:gcc -o testAddLib testAddLib.c -L. -lmyAddLib

-L指定库路径,-lmyAddLib指定库的名称,不包含lib.a两部分。

第二节:动态函数库

动态函数库又叫共享库(share lib)。它是在运行时,由系统的动态函

数库"lib/ld.so"负责动态加载。

动态函数库也有自己的命名规则:lib+动态库名称+.so+.+版本号;比如libC++.so.6。

动态函数库有两种使用方式:动态链接(隐式调用)和动态调用(显式调用,利用lib/ld.so提供的函数,利用函数指针,动态调用一个类库中包含的函数,不需要知道动态库的头文件)。

隐式调用和显示调用:

隐式调用使用方便简单, 但其和静态库相似, 在编译期就和程序绑定了,灵活性差, 并且其生存期和进程一样, 进程开始, 调用开始, 进程结束, 动态库才卸载. 另外还需要将整个动态库全部加进内存.

显式调用使用起来比较复杂, 但是却可以在运行期间选择所需要调用的动态链接库, 并且可以控制动态库生存期, 需要加载时候再加载, 用完了就可以卸掉, 而且不用将整个动态库都放进内存, 只要加载要用到的函数即可.

隐式调用:

编写动态库文件

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

FileName : myAddLib.h

FileFunc : 定义头文件

Version : V0.1

Author : Sunrier

Date : 2012-05-02

Descp : Linux下实现动态库

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

#ifndef _MYADDLIB_H_

#define _MYADDLIB_H_

#ifdef __cplusplus

extern "C" {

#endif

int add(int ,int );

#ifdef __cplusplus

}

#endif

#endif

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

FileName : myAddLib.c

FileFunc : 定义动态库实现文件

Version : V0.1

Author : Sunrier

Date : 2012-05-02

Descp : Linux下实现动态库

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

#include

int add(int iArg1,int iArg2)

{

printf("iArg1= %d , iAgr2= %d \n",iArg1,iArg2);

return (iArg1+iArg2);

}

制作库文件:

1.gcc -fipc myAddLib.c -o myAddLib.o

2.gcc -share -o libmyAddLib.so.1 myAddlib.o

或者 gcc -fipc -share -o libmyAddLib.so.1 myAddLib.c

其中-fipc用来产生和位置无关代码,-share用来生成动态共享库

隐式使用动态库文件

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

FileName : testAddLib.c

FileFunc : 测试动态库文件

Version : V0.1

Author : Sunrier

Date : 2012-05-02

Descp : Linux下实现动态库

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

#include

#include "myAddLib.h"

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

{

int iNumber1,iNumber2,iSum = 0;

iNumber1 = 10;

iNumber2 = 20;

iSum = add(iNumber1,iNumber2);

printf("iSum=%d\n",iSum);

printf("Hello Sunrier!\n");

return 0;

}

编译目标文件

gcc -o testAddLib testAddLib.c -L. -lmyAddLib

-L指定动态函数库的位置供查找,注意L后面还有'.',表示动态函数库在本目录下查找。此时还不能立即./testAddLib,因为在动态函数库使用时,会查找/usr/lib或/lib目录下的动态函数库,而此时我们生成的库不在里边。

执行可执行文件

这个时候有好几种方法可以让他成功运行:

最直接最简单的方法就是把libmyAddLib.so放到/usr/lib或/lib中去或者修改LD_LIBRARY_PATH环境变量文件。

假设libmyAddLib.so在/home/Sunrier/lib

export LD_LIBRARY_PATH=/home/Sunrier/lib:$LD_LIBRARY_PATH

另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig。

/etc/ld.so.conf是非常重要的一个配置文件,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib或/lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig。

动态调用:

根据前面提到的生成头文件libmyAddLib.so文件。

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

FileName : testAddLib.c

FileFunc : 测试动态库文件

Version : V0.1

Author : Sunrier

Date : 2012-05-03

Descp : Linux下实现动态库

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

#include

#include

#define SOFILE "./libmyAddLib.so"

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

{

int iNumber1,iNumber2,iSum = 0;

void *hdl = NULL;//动态库句柄

hdl = dlopen(SOFILE,RTLD_LAZY);//打开动态链接库

if( NULL==hdl )

{

printf("No libmyAddLib.so file\n");

return 1;

}

/*函数指针*/

int(*add)(int,int);

add = dlsym(hdl,"add");//查找符号表,定位共享函数

char *error = dlerror();//检测错误

if( error )

{

printf("No function!\n");

return 1;

}

iNumber1 = 10;

iNumber2 = 20;

iSum = add(iNumber1,iNumber2);//调用此共享函数

//iSum = (*add)(iNumber1,iNumber2);//调用此共享函数

printf("iSum=%d\n",iSum);

printf("Hello Sunrier!\n");

dlclose(hdl);//关闭共享库

hdl =NULL;

return 0;

}

dlfcn.h包含了动态调用函数库的相关的函数。

void *dlopen (const char *file, int arg );

//打开一个动态库的文件,arg代表打开的方式

/*

RTLD_LAZY

Relocations are performed at an implementation-dependent time.

RTLD_NOW

Relocations are performed when the object is loaded.

RTLD_GLOBAL

All symbols are available for relocation processing of other modules.

RTLD_LOCAL

All symbols are not made available for relocation processing by other modules.*/

void *dlsym(void *handle, const char *name);

void *handle;

int *iptr, (*fptr)(int);

/* open the needed object */

handle = dlopen("/usr/home/me/libfoo.so.1", RTLD_LAZY);

/* find the address of function and data objects */

fptr = (int (*)(int))dlsym(handle, "my_function");

iptr = (int *)dlsym(handle, "my_object");

/* invoke function, passing value of integer as a parameter */

(*fptr)(*iptr);

char *dlerror(void);

/*If successful, dlerror() returns a null-terminated character string. Otherwise, NULL is returned.*/

int dlclose(void *handle);

/*If the referenced object was successfully closed, dlclose() returns 0.

If the object could not be closed, or if handle does not refer to an open object,

dlclose() returns a non-zero value. More detailed diagnostic information will be available through dlerror().*/

编译和生成目标文件:

#gcc testAddLib.c -o testAddLib -ldl

其中-ldl用于加载dl库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值