linux下的动态链接库和静态链接库到底是个什么鬼?(一)静态链接库的编译与使用
知识不等于技术,这句话真的是越工作的时间长越深有体会,学习到的知识只有不断的实践,才成真正在自已的心里扎下根,成为自身的一部分,所以无论如何,我希望我的博客可以一直写下去,慢慢的沉淀,终会有回报,无聊的时候想想,的确,写代码也是一种自娱自乐!
前几天在做项目时出了一个问题,大体就是:makefile里在编译可执行文件testappd的时候在有用-l去引用一个libtest.so,能编译通过,但是在加载运行的时候系统提示找不到这个lib而导致进程启动失败。后来知道在产品版本编译打包的时候这个lib并未被打包进去,这个问题后来解决了。但是出于好奇,我想搞清楚动态库和静态库的概念,以及之前做过另一个项目时以dlopen方式去引用动态库和makefile 去引用动态库这几种方式的不同。查找了网上的一些资料,看明白了,还需手动验证一下才放心。
首先说说静态链接库,说实话,有时候真心感觉计算机这些相关的各种高大上的词汇都是纸老虎,看上去高深的不行,其实当你捅开那层纸,就那么回事儿。
所谓静态链接库,说白了就是在你把写好的代码编译的时候,就把你引用的库一起给编进去了,从此后你编出来的执行程序跟外面都不再有任何关系,即使这个库更新了,你也搭不上边儿,其次,如果系统中许多类似的程序都需要用到这个库,那么各自在编译的时候都需要把这个库给编进去,浪费存储空间(加载到内存里应该也是浪费内存空间的)。linux系统中静态库的名字一般叫
xxx.a, 所以如果你看到一个以 .a结束的文件那么它多半就是一个静态链接库文件。
废话少说,我们直接上干货,看看静态库是如何被编译出来以及如何被使用的
首先我们写了一个sum.c,如下,很简单,里面只有一个Sum函数,把两个数相加的和返回
1 int Sum(int Number1, int Number2) 2 { 3 return Number1 + Number2; 4 }
当然还要写一个声明它的sum.h
int Sum(int Number1, int Number2);
最后来一个调用这个sum函数的主函数, 打印返回的结果
1 #include<stdio.h> 2 #include<sum.h> 3 4 void main() 5 { 6 int Num1 = 1; 7 int Num2 = 2; 8 int iRet = 0; 9 10 iRet = Sum(Num1, Num2); 11 printf("Num1 + Num2 = %d.", iRet); 12 return; 13 }
接下来我们编译静态库,我的笔记本是mac os环境,打开终端后用vim写代码, gcc等相关工具直接就能用,版本没注意,反正能用就行
1 192:zch kane$ ls 2 main.c sum.c sum.h 3 192:zch kane$ gcc -c sum.c 4 192:zch kane$ ls 5 main.c sum.c sum.h sum.o 6 192:zch kane$ 7 192:zch kane$ 8 192:zch kane$ ar cr libsum.a sum.o 9 192:zch kane$ ls 10 libsum.a main.c sum.c sum.h sum.o 11 192:zch kane$
如上,我们用ar这个工具来编译静态库,cr标志告诉ar将object文件封装
然后我们编译主程序并运行:
192:zch kane$ gcc -o sumappd main.c -L . -lsum 192:zch kane$ ls libsum.a main.o sum.h sumappd main.c sum.c sum.o 192:zch kane$ ./sumappd Num1 + Num2 = 3
“-L .”指明了当前lib所在的路径是在本目录,-l表示链接libsum.a这个lib库,很好理解。