函数库中存放了大量函数的二进制文件,可供用户进行调用。在Linux系统下有两种函数库:静态库和动态
库。
一、静态库(.a后缀)与动态库(.so后缀)的区别
1、用户使用库的时刻不同:
静态库是用户在编译时进行调用;动态库是用户在进行程序时调用。
2、使用场合不同:
静态库适用于代码量小的应用程序;动态库适用于代码量大的应用程序。
3、静态库与动态库的优缺点:
1)静态库:
如果调用静态库中的函数,则在“编译”时会把静态库中相关代码复制到可执行文件中。
优点:可执行文件中包含相关代码,运行时不在依赖于静态库,速度更快。
缺点:是可执行文件的体积增大、占用更多磁盘空间,静态库经过升级后需要重新编译源文件,并在“编译”时
链接静态库。
2)动态库:
动态库在运行时进行调用,仅仅记录用到共享库中的相关符号,而不复制共享库中的相关代码。
优点:节省存储空间,不占用跟多磁盘空间;库的升级更加方便,无需再次编译源文件。
缺点:程序每次运行时都需要加载动态库,
二、函数库的制作
1、静态库.a的制作步骤
1、确定静态库中每个库函数的功能、接口。
2、编写实现每个库函数的.c文件及对库函数进行声明的.h文件
3、将多个静态库函数的.c源码文件编译汇编生成.o的二进制文件
例:gcc -c mylib.c -o mylib.o
4、创建静态库,并将所包含的.o文件添加进来
命令:ar crs libmylib.a mylib.o
说明:libmylib.o 是静态库文件的名称,简称静态库文件名;以“lib”前缀开始,“.a”后缀结尾表示一个
静态库;中间的mylib表示库的名称。注意:库名 != 库文件名,库名很重要,在编译
阶段引用库函数时使用的是库名而不是库文件名。
mylib.o 要添加到静态库中的.o文件,此处为特例,一般此处需要用到多个.o文件。
在这里静态库的制作基本上已经完成了,在调用次静态库中的函数时只需要引用该静态库的头文件并且在
编译时链接静态库就可以了。
2、静态库库函数的调用
在测试代码编写完成之后就可以对测试代码进行编译;记得在编译时链接静态库即可。静态库的链接命令
如下:
gcc test.c -o test -L. -lmylib
gcc test.c -o test -L. -lmylib -I. mylib.h
说明:
-L. -L用来添加一个库的搜素路径,而-L.表示该静态库在当前目录下,即当前路径。
-lmylib -l表示进行链接,mylib是链接的库名称而不是库文件名称。
-I 用来指定头文件,如果在测试文件的代码中利用#include 添加了头文件则可以省略此项。
执行静态库的链接命令:
3、动态库的制作
1、确定动态库中库函数的功能、接口
2、编写库函数的源码
3、对库函数的源码进行编译,汇编生成.o的目标文件,
gcc -c -fPIC mylib.c -o mylib.o
说明:PIC position indenpent code,即位置无关代码。-fPIC是告诉编译器生成位置无关代码,所谓
的位置无关代码即生成的.o文件的代码可以被加载到任意位置执行,这是共享库的特点。
4、创建共享库,并将库函数的.o文件添加进来
共享库的创建命令:gcc -shared -o libcommon.so.1 mylib.o
说明:-shared 表示生成一个共享库文件
libcommon.so.1 共享库文件的名称;
lib 以lib开头,表示库
common 共享库的库名称
.so 以.so为后缀表示共享库
.x x为数字,表示该共享库的版本。
5、为共享库创建符号链接
ln -s libcommon.so.1 libcommon.so
软连接:libcommon.so可以指向共享库的不同版本,比较灵活。
6、添加共享库的加载路径
此时共享库已经创建完毕,但是还是无法使用共享库。因此我们需要指定共享库的加载路径,以便程序运
行时可以找到动态库。
1、设置相应的环境变量,添加库的搜素路径。
指向“export LD_LIBRARY_PAHT=$LD_LIBRARY_PATH:.”命令,将当前的路径添加到库的搜索路径中。但
是此方法只对当前终端有效。
2、在目录“/etc/ld.so.conf.d”下新建一个“*.conf”文件,并执行“ldconfig”命令进行刷新。
说明:“/etc/ld.so.conf.d”是一个目录,在该目录下有若干后缀为“.conf”的文件,每个文件中的内容都是
相应动态库的路径。可以在该目录下新建一个“.conf”的文件,把新建的库的路径写入此文件,然后利用
ldconfig命令刷新生效。
4、链接共享库
共享库创建完毕并添加库的加载路径之后共享库中的库函数便可以被调用。库函数的调用形式如下:
gcc -o test test.c -L. -lcommon
可以发现共享库的链接和静态库的链接方式一样,那么系统是如何做出选择的呢?
1、gcc编译器默认优先去链接动态库,如果动态库不存在再去链接静态库。
2、如果想直接去链接静态库,可以加上-static选项显式的去链接静态库。