分类: C/C++
2012-10-03 17:04:30
库分为静态库与动态库两种,我们在写程序的时候会调用很多库函数,如:printf,scanf等等,这些函数都在libc.a这个库中,对每个C程序来说都是可用的。
静态库:
要是不使用库函数,那么我们在编译程序的时候将会使用诸如:gcc main.c /usr/lib/printf.o这种形式来产生我们的可执行文件,这是一个容易出错且耗时的工作,所以我们想出了静态库这个概念,以解决这些缺点。事实上,在链接的时候,链接器只拷贝被程序引用的目标模块,这就减少了可执行文件在磁盘与存储器中的大小。我们使用 ar 这个工具来创建我们的静态库,先生成*.o ,也就是 gcc -c 选项产生的文件,之后我们就可以使用 ar -r *.a *.o来创建静态库。举个例子:
静态链接后的目标程序,执行时不再需要原库文件,这是与动态链接的最大区别。
在产生main这个可执行文件的过程中,我们的链接器可是做了大量的工作的,在这里就不赘述了。
但是静态库有一些明显的缺点,它和所有的软件一样,需要定期的维护与更新,然后显示地将他们重新进行链接。另外一个问题就是,我们每个C程序,几乎都使用了标准的I/O函数,在运行时,每个库函数都会被复制到每个进程的文本段中,这将极大的浪费空间。
由此我们出现了动态链接这个概念,也就是使用共享库(动态库)。
动态库:
在运行时,它可以加载到任意的存储器地址,并和存储器的程序链接起来,这个过程叫做动态链接,是由动态链接器来完成的,在UNIX中它是以.so后缀来表示的。所有引用该库的可执行文件共享这个.so文件中的代码和数据。我们使用gcc -shared -fPIC -o *.so *.c
来创建共享库,-fPIC选项表示的是创建与位置无关的代码 。
动态链接分为显示链接与隐式链接,下面举个隐式链接的例子:
基本的思路是当创建可执行文件时,静态的执行一些链接,然后在程序运行时,动态的完成链接过程。在这里要注意的是,*.so中没有任何的代码和数据被拷贝到可执行文件中。
当然我们还可以在应用程序中加载和链接共享库这种显式的链接。
UNIX中使用函数dlopen,dlsym,dlerror,dlclose,这四个成员来完成链接的操作。
执行流程如图:
大家可以通过察看man手册来了解这几个函数的具体用法,在man手册中的最后还给出了这几个函数用法的例子。