第一章 库
1.库文件
库是一组预先编译好的函数集合,这些函数都是按照可重用的原则编写的,通常是相互关联的函数组成以执行某项常见任务。
库文件的名字总是以lib开头,随后的部分指明这是什么库(例如,c代表C语言库,m代表数学库),文件名的最后部分以点 . 开始,例如libc.a。其类型可分为:
- .a代表传统的静态函数库;
- .so代表共享函数库。
函数库通常同时以静态库和共享库两种格式存在。可以通过给出完整的路径名或使用 -l 标志来告诉编译器要搜索的库文件。例如:
$ gcc -o fred fred.c /usr/lib/libm.a
$ gcc -o fred fred.c -lm
上面两条命令要求编译器编译文件fred,并且在搜索标准的c语言函数库外,还要搜索数学库,以解决函数引用问题。第二条为简写。
2.静态库
静态库,也称作归档文件,惯例以 .a 结尾。可以简单的通过ar(代表archive,即建立归档文件)程序建立和使用gcc -c命令对函数分别进行编译。
实验:
本例中包含两个函数,然后将在一个示例程序中调用其中一个。这两个函数分别为fred和bill,它们只打印欢迎信息。
1.)首先,为两个函数分别创建各自的源文件(fred.c和bill.c):
/*************第一个文件fred.c*******************/ #include <stdio.h> void fred(int arg) { printf("fred: we passed %d\n",arg); } /*************第二个文件bill.c*******************/ #include <stdio.h> void bill(char *arg) { printf("bill: we passed %s\n",arg); }
2.)编译这两个文件产生要包含在库文件中的目标文件(gcc -c //只编译不链接),bill.o 和 fred.o。
$gcc -c bill.c fred.c
3.)为库文件创建一个头文件,这个头文件将声明库文件中的函数,所有希望使用库文件的应用程序都应该包含此头文件。
/************************lib.h******************
***************声明bill与fred的函数***************/ void bill(char *); void fred(int);
4.)再编写一个调用bill的程序。
/********program.c*********/ #include <stdlib.h> #include "lib.h" int main() { bill("hello world!"); exit(0); }
5.)现在可以编译并测试这个程序了。先将program.c编译成目标文件program.o,在与bill.o链接
$ gcc -c program.c $ gcc -o program program.o bill.o $./program
6.)现在我们将创建并使用一个库文件。使用ar程序床架一个静态库,并将刚才的目标文件添加进去。
$ ar crv libfoo.a bill.o fred.o
7.)现在就可以使用库来创建程序了。
$ gcc -o program program.o libfoo.a /*执行一下*/ $./program bill: we passed helo world!
8.)要查看那些函数被包含在目标文件/函数库或可执行文件中,可以使用nm命令。
$ nm libfoo.a bill.o: 00000000 T bill U printf fred.o: 00000000 T fred U printf
3. 共享库
静态库的缺点:当同时运行许多应用程序时并且它们都是使用来自同一个函数库的函数时,内存中就会有同一个函数的多份副本,而且在程序文件中也会有很多同样的副本。
共享库可以解决上述问题,共享库与静态库的保存位置是一样的,但是后缀不一样 .so。
当程序使用共享库时,它不在包含函数代码,而是引用运行时可以访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要,共享库才被加载到内存中。
通过这种办法,系统可以只保留共享库的一份副本供许多程序使用,并且在磁盘上也仅保存一份。另一个好处是共享的更新可以独立于依赖他的程序。

浙公网安备 33010602011771号