动态库和静态库分析
一.概述
上一篇文章提到了静态链接和动态链接,本文对动态库和静态库做一个分析总结。
本质上来说库是一种可执行代码的二进制形式,是目标文件的集合。可以被操作系统载入内存执行。由于windows和linux的本质不同,因此二者库的二进制是不兼容。Linux系统支持的函数库包括静态库和动态库(共享库),通常放在目录 /lib, /user/lib下面。
静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。当然这也会称为的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。
动态库:这类库的名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用函数库里相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便(不需要重新编译)。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减少应用程序的体积。
二.动态库 静态库 实例
A(vendor1)公司提供libcrypto库,B(vendor2)公司提供libfunc库。C公司为客户,需要使用A、B两公司提供的库。
A公司的函数有:
Step1:将其源代码生成静态库文件libcrypto.a(静态库文件必须由 *.o 文件生成,需先编译成 *.o 文件)
Step2:将其源代码生成动态库文件 libcrypto.so(由 *.c 文件生成 )
step3:同样的方法将B公司的源代码生成动态库(libfunc.so)静态库(libfunc.a)
step4:A、B公司分别把自己的(动态静态)库文件和头文件(*.h)提供给C公司,C公司便可以使用A、B公司的函数,但不能查看和修改源代码。
step5:C公司将其从AB公司获得的库文件和头文件放在自己lib文件夹下面
step6:C公司只需写自己主函数,可自由调用A、B提供的函数库。
Step7:编译使用动态库文件
从上面的运行结果中,我们可以看到:
A.当动态库和静态库同时存在的时候,gcc默认使用的是动态库。如果强制使用静态库则需要加-static选项支持。
B.动态库生成的可执行文件,app不能正常的运行。这是因为当系统加载可执行代码时候,仅仅知道其所依赖的库的名字还是不够的,还需要知道绝对路劲。此时就需要系统动态载入器(dynamic linker/loader)。对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的DT_RPATH段---环境变量LD_LIBRARY_PATH、/etc/ld.so.cache文件列表、/usr/lib、/lib目录找到库文件后将其载入内存。
如果我们要成功运行链接动态库生成的文件,一种最直接的方法,就是把生成的动态库拷贝到/usr/lib或/lib中去。此时链接动态库生成的文件可以正常运行。
Step8:编译使用静态库文件