首页 > 代码库 > 动态链接

动态链接

静态链接虽然解决了一下问题 但是仍旧有很多缺点。比如浪费内存和磁盘空间,模块更新也比较困难。

最主要的是 我们正常一个c语言程序 要使用诸如printf strlen 等等之类c语言库的代码。一个c语言程序要使用1mb的内存来使用它。

如果有100个程序的话 就是100mb的内存。这是无法忍受的。因为内存太贵了。

再有一个就是,假设我们有一个静态库 里面有20个 目标文件,那么一旦这20个文件有一个更新了新版本,哪我们就要从新打包,实在是很不方便。

所以后来,就出现了动态链接这个技术。并沿用至今。

 

简单来说动态链接就是把链接过程推迟到运行时再进行。

 

举个栗子 我们有 程序a 和程序b  这2个程序都依赖于库c。 当我们使用动态链接时,程序a一开始不需要链接c。而是当操作系统真正开始运行a的时候

发现a依赖库c,于是操作系统就去链接c了。此时c在 内存中。然后程序b也被运行,这个时候也要进行动态链接,但是此时发现库c已经在内存中,于是

内存中只有 a b c 三块。 但是如果采用静态链接那就是 a c b c 四块内存了。

 

所以我们可以看出来,动态链接的基本思想就是把程序按照模块拆分成各个相对独立的部分,在程序运行时才将他们链接在一起,而不是像静态链接那样把所有

的程序模块都链接成一个单独的可执行文件。

 

实际上在linux中 动态链接库 就是so 后缀名,而windows就是dll 为后缀名的文件了。经常打游戏的尤其是盗版游戏的肯定熟悉dll。

 

下面我们来实际操作一下动态链接的过程。

首先我们定义一个文件 program1.c

1 #include "Lib.h"2 int main()3 {4     foobar(1);5     return 0;6 }

然后定义program2.c

1 #include "Lib.h"2 int main()3 {4     foobar(2);5     return 0;6 }

然后定义Lib.h

1 #ifndef LIB_H2 #define LIB_H3 void foobar(int i);4 #endif

最后定义lib.c

1 #include <stdio.h>2 void foobar(int i)3 {4     printf("printing from Lib.so %d\n",i);5 }

然后我们把我们的lib.c编译成我们的动态库。

然后编译他,最后运行他,看看结果。

 

这个地方实际上我们要注意的是, 在gcc -o的时候 他发现 后面是动态库 于是这个地方 就不会去链接他。

 

而是等到真正运行期的时候 才会去链接他。这是和静态库最大的不一样。

 

在静态链接时,整个程序最终只有一个可执行文件,而动态链接 则有若干个文件。

 

我们来看一下这个so 动态库。

你看这个地址 0x000000000000 一看就知道这个地址是无效的,所以我们能推测出 在编译期 这个共享库的地址是不确定的

一定得等到运行期才能确定。

 

动态链接