Linux中库的生成和使用

来源:互联网 发布:什么软件借钱最靠谱 编辑:程序博客网 时间:2024/05/16 01:50

1    库的生成和使用

库可以有三种使用的形式:静态、共享和动态。静态库的代码在编译时就已载入到开发人员开发的应用程序中。而共享库在程序开始运行时才载入,在编译时只是简单地指定需要使用的库函数。动态库则是共享库的另一种变化形式,动态库也是在程序运行时载入,但与共享库不同的是,程序中使用到的库函数不是在程序开始运行时,而是在程序中的语句需要使用该函数时才载入。动态库可以在程序运行期间释放动态库所占用的内存,腾出空间供其它程序使用。

动态库的后缀通常为.so (Shared Object),静态库的后缀通常为.a (Archive)。在默认情况下,共享库通常为绿色,而静态库为黑色。

为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhello.so.1.0。但是由于程序链接默认以.so.a为文件后缀名,所以为了能够正常使用这些库,通常使用建立符号链接的方式。

ln-fs libhello.so.1.0 libhello.so

ln–fs libhello.a.1.0 libhello.a

/lib/ld.so:Linker andloader;

/etc/ld.so.conf:List of directories that contain libraries;

/etc/ld.so.cache:List of the libraries in libraries mentioned in/etc/ld.so.conf.

1.1         库的生成

1.1.1       生成静态库

arkey [modifiers] [reference-member] archive [members]

只有一个key可能被用到,但是一个key可以和多个modifiers联合使用。reference-member是库中已经存在的某一个成员的名字。

key

d    :从库中删除成员。

m   :将成员移动到库的末尾。

a,b,i可以影响该key的操作。

p    :打印库中的成员。

q    :添加成员到库的末尾,withoutchecking the replacement。

a,b,i并不能影响该key的操作。

r    :替换库中的成员,并把替换的成员移动到库的末尾。

a,b,i可以影响该key的操作。

t     :列出整个库的内容或者是只列出指定的成员。

x    :从库中提取所有成员或者是指定的成员。

modifiers

a    :和r或者m一起使用在reference-member之后放置成员。

b/i  :和r或者m一起使用在reference-member之前放置成员。

c    :创建库。

o    :当提取成员时,保持成员原有的时间戳,否则将改变成员的时间戳为提取的时间。

s     :Write an object-file index into the archive。

Running ar son an archive is equivalent to running ranlibon it。

S    :禁止生成archive symbol table。

u    :只能和r一起使用,只替换那些已经被更新的成员。

例如:

$arrc libhello.a.1.0 hello.o

$ln-fs libhello.a.1.0 libhello.a

 

1.1.2       生成动态库

动态库的生成由gcc来完成,通常指定版本号:

$gcc-shared -o libhello.so.1.0 hello.o -Wl,-soname, libhello.so.1.0

$ln-fs libhello.so.1.0 libhello.so

实际上每一个库都有一个soname,在程序执行期间,程序会使用soname查找库,而不是库名。这样的话在程序运行期间,可以有多个名字相同但soname不同的库存在,而程序可以根据soname找到对应的库文件。

1.2         库的使用

如果要使用一个库(静态库libhello.a或动态库libhello.so),则必须准备两个文件:一个就是库文件libhello.a或libhello.so;另外一个就是向用户提供函数声明的头文件(hello.h)。

假设hello.h中提供了sayhello()的函数声明,而用户编写的test.c需要使用sayhello()函数:

#include“hello.h” // 必须保存在头文件的搜索路径中

intmain( )

{

sayhello();

return 0;

}

1.2.1       静态库的使用

$gcc-o test test.c -Wl,-Bstatic –Ldir -lhello

静态库文件只在编译链接时需要,可执行程序一旦编译成功,则放在哪里都可以运行,不再需要静态库文件的支持。

1.2.2       动态库的使用

$gcc-o test test.c –W1,-Bdynamic –Ldir –lhello

因为默认进行的就是动态库链接,所以上面的命令可以简写为:

$gcc-o test test.c –Ldir –lhello

需要注意的是动态库文件不但在编译链接时需要,即使可执行程序编译成功,它的运行业需要动态库文件的支持,所以动态库必须能够被搜索到,有两种方法:

(1) 把动态库文件拷贝到/usr/lib和/lib目录下。

(2) 修改/etc/ld.so.conf文件,加入库文件所在的路径,并执行ldconfig刷新。

如果要和多个库进行链接,而且每个库的链接方式不一样,其命令为:

$gcc-o test test.c –W1,-Bstatic –Ldir -lhello –W1,-Bdynamic –Ldir -lbye

1.3         库的查询

1.3.1       nm

nm打印出库中所有的符号。库既可以是静态的也可以是动态的。nm列出的符号有:

A:absolute,will not be changed by future link。

B:the symbolis in the un-initialized data section。

C:the symbolis common,common symbols are in the un-initializeddata section。When linking,multiplecommon symbols may appear with the same name。

D:the symbolis in the initialized data section。

G:the symbolis in the initialized data section for small objects。

I:the symbolis an indirect reference to another symbol。

N:the symbolis a debugging symbol。

R:the symbolis in a read only data section。

S:the symbolis in a un-initialized data section for small objects。

T:the symbolis in the text(code) section。

U:the symbolis undefined。

V:the symbolis a weak object symbol。When a weak defined symbol is linked with anormal defined symbol,the normal defined symbol is used with noerror。When a weak undefined symbol is linked,the value of the weak symbol becomes zero with noerror。

W:the symbolis a weak symbol that has not been specifically tagged as a weak object symbol。When a weak defined symbol is linked with a normaldefined symbol,the normal defined symbol is used with noerror。When a weak undefined symbol is linked,the value of the weak symbol is determined in asystem-specific manner with no error。Uppercaseindicates that a default value has been specified。

-:the symboltype is unknown。

 

nm[options] [objfiles]

-a:打印所有的符号,包括debugonly符号(默认是不打印的)。

-A:打印每一个符号的所属文件名。

-C:将符号转译为可读形式。

-D:只打印dynamicsymbols。

-g:只打印外部符号。

-u:只打印未定义的符号。

--defined-only:只打印定义过的符号。

-s:当打印库成员的符号时,打印出它们的索引,也就是这些符号属于哪个模块。

-S:打印每一个定义过符号的大小,而不打印它们的值。

假设希望知道hello库中是否定义了sayhello():

$nmlibhello.so | grep sayhello

1.3.2       ldd

ldd是LibraryDependency Display缩写,它的作用是显示一个可执行程序或一个共享库必须使用的共享库。

lddprograms/shared libraries

1.3.3       ldconfig

库安装到系统以后,为了让动态链接库为系统所认识及共享,就需要运行ldconfig。ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的链接和缓存文件。缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库的名字列表,ldconfig通常在系统启动时运行,当用户安装了一个新的动态链接库时,就需要手工运行这个命令:

ldconfig[options] [libs]

-n:仅扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录。

-fconf:使用conf文件代替/etc/ld.so.conf

-Ccache:使用cache文件代替/etc/ld.so.cache

-p:打印在当前cache中存放的目录和库文件列表。

-N:Do not rebuild cache,links arestill updated。

-X:Do not update links,cache isstill rebuilt。

原创粉丝点击