linux下的动态链接库和静态链接库到底是个什么鬼?(一)静态链接库的编译与使用

时间:2022-04-13 15:49:43

    知识不等于技术,这句话真的是越工作的时间长越深有体会,学习到的知识只有不断的实践,才成真正在自已的心里扎下根,成为自身的一部分,所以无论如何,我希望我的博客可以一直写下去,慢慢的沉淀,终会有回报,无聊的时候想想,的确,写代码也是一种自娱自乐!

    前几天在做项目时出了一个问题,大体就是: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库,很好理解。