《程序员的自我修养》p7 动态链接—为什么要动态链接

为什么要动态链接

《程序员的自我修养》p7 动态链接—为什么要动态链接

内存和磁盘空间

在多进程操作系统下,静态链接是比较浪费内存空间的;一个普通程序除了printf,scanf等公用库函数,还有很多其他库函数和所需要的辅助数据结构;
如上图所示的program1和program2分别包含program1.o和program2.o两个模块,并且他们还公用lib.o模块;
在静态链接情况下,因为program1和program2都用到了lib.o模块,所以它们同时在链接输出的可执行文件program1和program2有两个副本。当我们同时运行program1和program2时,lib.o在磁盘和内存中都有两个副本。当程序中存在多个这样的被共用的模块副本时,就造成了内存浪费;

程序开发和发布

静态链接对于程序的更新、部署和发布也带来诸多麻烦;一旦程序中有任何模块更新,整个程序就要重新链接、发布给用户;

动态链接

把链接这个过程推迟到运行时再进行,这就是动态链接的基本思想
《程序员的自我修养》p7 动态链接—为什么要动态链接
上面的做法解决了共享的目标文件存在多个副本浪费磁盘和内存空间的问题,可以看到此时的磁盘和内存中只存在一份lib.o文件;此外,在内存中共享一个目标文件模块的好处不仅仅是节省内存,还减少了物理页面的换入换出,也可以增加CPU缓存的命中率,因为不同进程间的数据和指令访问都集中在了同一个共享模块上。
《程序员的自我修养》p7 动态链接—为什么要动态链接

动态链接如何实现

动态链接涉及运行时的链接及多个文件的装载,必须要有操作系统的支持,因为动态链接的情况下,进程的虚拟地址空间的分布会比静态链接情况下更为复杂;
在Linux
系统中,ELF动态链接文件被称为动态共享对象(DSO),简称“共享对象”,它们一般都是以“.so”为扩展名的一些文件;在Windows系统中,动态链接文件被称为动态链接库,就是“.dll"文件

从本质上讲,普通可执行程序和动态链接库都包含指令和数据。在使用动态链接的情况下,程序本身被分为程序主要模块(program1)和动态链接库(libc.so),但实际上它们都是整个程序的一个模块;

在Linux中,常用的C语言库的运行库glib.c,它的动态链接形式的版本保存在"/lib"目录下,文件名叫做“libc.so”,整个系统只保留了一份C语言库的动态链接文件“libc.so”,而所有的C语言编写的、动态链接的程序都可以在运行时使用它。当程序被装载时,系统的动态链接器会将程序所需要的所有动态链接库(最基本的就是libc.so)装载到进程地址空间中,并且将程序中所有未决议的符号绑定到相应的动态链接库中,并进行重定位工作。

程序与libc.so之间真正的链接工作是由动态链接器完成的,并非前面提到的静态链接器ld;也就是说,动态链接是把链接这个过程从本来的程序装载前被推迟到了装载的时候。