静态库和共享库制作

1静态库和共享库

*本节就如何创建和使用程序库进行论述。所谓“程序库”,简单说,就是包含了数据

和执行码的文件。其不能单独执行,可以作为其它执行程序的一部分来完成某些功能。库的

存在,可以使得程序模块化,可以加快程序的再编译,可以实现代码重用,可以使得程序便

于升级。程序库可分静态库(static library)和共享库(shared object)

 

A:静态库

是在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分;共享库,是在

执行程序启动时加载到执行程序中,可以被多个执行程序共享使用。

建议库开发人员创建共享库,比较明显的优势在于库是独立的,便于维护和更新;而静

态库的更新比较麻烦,一般不做推荐。然而,它们又各有优点,后面会讲到。

节所讲述的执行程序和库都采用ELF(Executable and Linking Format)格式,尽管GNU

GCC工具可以处理其它格式,但不在本节的讨论范围。

静态库可以认为是一些目标代码的集合。按照习惯,一般以“.a”做为文件后缀名。使

ar(archiver)命令可以创建静态库。因为共享库有着更大的优势,静态库已经不经常使

用。但静态库使用简单,仍有使用的余地,并会一直存在。有些Unix系统,如Solaris 10

已经基本废弃了静态库。

静态库在应用程序生成时,可以不必再编译,节省再编译时间。但在编译器越来越快的

今天,这一点似乎已不重要。如果其他开发人员要使用你的程序,而你又不想给其源码,提

供静态库是一种选择。从理论上讲,应用程序使用了静态库,要比使用动态加载库速度快

1-5%,但实际上可能并非如此。由此看来,除了使用方便外,静态库可能并非一种好的选

择。

要创建一个静态库,或要将目标代码加入到已经存在的静态库中,可以使用以下命令:

 

ar rcs libmylib.a file1.o

 

file2.o以上表示要把目标码file1.ofile2.o加入到静态库libmylib.a(ar的参数

r)。若libmylib.a不存在,会自动创建(ar的参数c)。然后更新.a文件的索引,使之包含新

加入的.o文件的内容(ar的参数s)

静态库创建成功后,需要链接到应用程序中使用。使用gcc-l选项来指定静态库,使

-L参数来指定库文件的搜索路径。比如上述例子应指定-lmylib,所有库文件名都以lib

头,开头的lib在指定参数时应省略。-l-L之后都直接带参数而不跟空格。

在使用gcc时,要注意其参数的顺序。-l是链接器选项,一定要放在被编译的文件名称

之后;若放在文件名称之前则会连接失败,并会出现莫名其妙的错误。这一点切记。

 

B:共享库

共享库的创建比较简单,基本有两步。首先使用-fPIC-fpic创建目标文件,PIC

pic表示位置无关代码,然后就可以使用以下格式创建共享库了: gcc -share -Wl,-

soname,your_soname -o library_namefile_list library_list 下面是使用a.cb.c创建

库的示例:

 

相关命令:

gcc –fPIC –c XX.c

gcc –fpic –c XX.c

gcc -shared -Wl,-soname,libmyab.so.1-o libmyab.so.1.0.1 a.o b.o

 

libmyab.so.1称之为soname,

libmyab.so.1.0.1称之为realname

libmyab.so  称之为linker name

 

按照共享库的命名惯例,每个共享库有三个文件名:real namesonamelinker

name。真正的库文件(而不是符号链接)的名字是realname,包含完整的共享库版本号。

soname是一个符号链接的名字,只包含共享库的主版本号,主版本号一致即可保证库函

数的接口一致,因此应用程序的.dynamic段只记录共享库的soname,只要soname一致,这个

共享库就可以用。如libmyab.so.1libmyab.so.2是两个主版本号不同的libmyab,有些应

用程序依赖于libmyab.so.1,有些应用程序依赖于libmyab.so.2,但对于依赖libmyab.so.1

的应用程序来说,真正的库文件不管是libmyab.so.1.10还是libmyab.so.1.11都可以用,所

以使用共享库可以很方便地升级库文件而不需要重新编译应用程序,这是静态库所没有的优点。

注意libc的版本编号有一点特殊,libc-2.8.90.so的主版本号是6而不是22.8

linker name仅在编译链接时使用,gcc-L选项应该指定linkername所在的目录。有

linker name是库文件的一个符号链接,有的linker name是一段链接脚本。例如上面的

libc.so就是一个linkername,它是一段链接脚本:

 

C:共享库加载

在所有基于GNUglibc的系统中,在启动一个ELF二进制执行程序时,一个特殊的

程序“程序装载器”会被自动装载并运行。在linux中,这个程序装载器就是/lib/ldlinux.

so.X(X是版本号)。它会查找并装载应用程序所依赖的所有共享库。被搜索的目录保存在/etc/ld.so.conf文件中。当然,如果程序的每次启动,都要去搜索一番,势必效率不

堪忍受。Linux系统已经考虑这一点,对共享库采用了缓存管理。ldconfig就是实现这一功

能的工具,其缺省读取/etc/ld.so.conf文件,对所有共享库按照一定规范建立符号连接,

然后将信息写入/etc/ld.so.cache/etc/ld.so.cache的存在大大加快了程序的启动速

度。

 

D:案例说明:

D1:创建一个目录,mycal

mkdir mycal

 D2:创建4c文件盒1.h,分别实现加减乘除

 add.c

 

 sub.c

mul.c

dive.c

common.h

  编写main.c

#include <stdio.h>

#include "common.h"

 

int main(void)

{

    printf("%d", add(5, 4));

    return 0;

}

D3制作静态库(加上-fPIC后生成的目标文件和位置无关,注意要加上这个)

查看静态库信息:

使用静态库(程序扔到任何电脑都可以运行,因为静态库相当于包含到了静态库中)

gcc -Isrc main.c libmycal.a –o app(-Isrc是为类引用common.h)

ldd app命令检测的是共享库,不检测静态库

上面的过程相当于libmycal.amain.c进行组合,生成app

  D4制作共享库,

  移动目录如下结构:

 

这时候生成了realname:    libmycal.so.1.10

D5设置共享库加载路径

  打开共享库路径配置文件

  sudo vi /etc/ld.so.conf

  最后一行添加mycal路径,截图如下,若不配置下面的信息,它后后面的gcc执行的命令和ldd命令回报没有找到库的提示信息。(下面配置告诉库所在的位置)

 

sudo ldconfig –v(输入后输出一堆结果,如果还是发现没有生成libmycal.so.1,这时候要去除缓存文件/etc/ld.so.cache  命令是:sudo rm –rf/etc/ld.so.cache

gcc main.c libmycal.so.1.10 -o app

 

ldd app查看程序运行的时候的依赖信息

如果用ldd app查看还是没有看到依赖,要去掉依赖文件,要删除的缓存文件是:/etc/ld.so.cache

注意:共享库和main.c共同使用的时候,在这个过程中相当于生成了main.o,符号记录表。app运行的时候依赖共享库版本。

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值