静态库
静态库可以简单的看成是一组目标文件(.o/.obj文件)的集合,即将多个目标文件压缩打包成一个文件。对应的链接方式为静态链接,即在使用该静态库时,会将自己编写的程序的目标文件和静态库文件一起链接生成可执行文件。在运行该程序时,静态库中的函数在代码段有自己固定的地址空间。
静态库的特点
- 静态库对函数库的链接是放在编译时期完成的,即在程序的编译阶段就完成了自己编写的程序生成的目标文件与静态库的链接;
-
程序在运行时与静态库中的函数库再无瓜葛,因为此时已经将静态库中的函数都链接到了可执行文件中,运行可执行文件时不再需要静态库中的函数库;
-
静态库的缺点,浪费空间和资源,因为所有需要与静态库链接的程序,均需要与该静态库链接生成一个可执行文件,如果一个静态库在运行时会占用1M内存,那么如果有1000个这样的程序则会1G的内存。
程序在运行时与静态库中的函数库再无瓜葛,因为此时已经将静态库中的函数都链接到了可执行文件中,运行可执行文件时不再需要静态库中的函数库;
静态库的缺点,浪费空间和资源,因为所有需要与静态库链接的程序,均需要与该静态库链接生成一个可执行文件,如果一个静态库在运行时会占用1M内存,那么如果有1000个这样的程序则会1G的内存。
静态库的创建
静态库的命名必须是lib+静态库名.a。
创建过程为:
1. 将代码文件编译成目标文件即.o文件。使用gcc -c或者g++ -c即可
2. 使用ar工具将目标文件打包成.a静态库文件。ar –crv lib静态库名.a 目标文件名,即可生成lib静态库名.a文件。
静态库的使用
使用静态库时需要指定静态库的搜索路径(-L)、指定静态库名(-l静态库名)。如:gcc 程序源文件 –L/静态库所在目录 -l静态库名(无lib前缀和.a扩展名)
动态库
动态库又称为共享库,是在程序运行时动态加载的库文件。
动态库的特点
- 动态库把对库函数的链接载入推迟到了程序运行阶段;
- 动态库可以实现进程之间的资源共享,即同一个动态库可以被多个进程链接,因此动态库又称共享库;
- 程序的升级变得简单,如果多个程序都链接了某动态库,当需要更新该动态库中的某个函数时,只需要对该动态库进行更新即可,不必将所有的程序都重新编译一遍;
- 如果使用显示调用动态库,则动态库的链接载入则完全可由程序员自己在代码中控制。(Java的JNI技术貌似就属于此类)
为什么使用动态库
- 空间浪费是静态库的一个问题
- 静态库对程序的更新、部署和发布也会带来麻烦。如果静态库更新则链接了该静态库的应用程序都需要重新编译,然后发布。
不同的应用程序调用相同的动态库,那么在内存中只需要有一份该共享库的实例,规避了空间浪费。同时,若动态库需要更新,则只需更新动态库即可,其他链接了该动态库的应用程序无需更新。
动态库的创建
动态库的命名规则:lib动态库名.so。每个动态库都有自己的名字,程序通过这个名字来告诉动态加载器该载入哪个库。在程序中,仅保存了指向该动态库的链接。
使用gcc –fPIC -c 文件名 生成目标文件,-fPIC是为了能够实现动态库在多个应用程序间共享,创建与地址无关的目标文件,使其能够放在内存的任意位置。
使用gcc –shared –o lib动态库名.so 目标文件名 来生成动态链接库。
动态库的使用
在编译源文件时,加载动态库的方法跟静态库是相同的,除此之外还需进行如下配置,否则在运行应用程序时,会报找不到这个动态库文件:
这是因为除了在编译阶段要告诉编译器该动态库的名字和目录外,还需告诉系统动态载入器(dynamic linker/loader)。
对于elf格式的可执行文件,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。
所以需要进行如下的配置(2选1):
1、将动态库文件复制到/lib或者/usr/lib下,则ld会默认的找到该文件,无需其他的操作。
2、如果安装在其他目录,则需要将其添加到/etc/ld.so.cache文件中:
(1)编辑/etc/ld.so.conf文件,加入库文件所在的目录;
(2)执行ldconfig命令,该命令会重建/etc/ld.so.cache文件。