程序员的自我修养:链接、装载与库 7 动态链接

1 为什么要动态链接

静态链接使得不同的程序员能够相对独立地开发和测试自己的程序模块,从某种意义上来讲大大促进了程序开发的效率,原先限制程序的规模也随之扩大。但是慢慢地静态链接的诸多缺点也逐步暴露出来,比如浪费内存和磁盘空间、模块更新困难等问题。

1.1 内存和磁盘空间

静态链接原理上很容易理解,实践上很难实现,在操作系统和硬件不发达的早期,绝大部分系统采用这种方案。随着计算机软件的发展,这种方法的缺点很快就暴露出来了,那就是静态链接的方式对于计算机内存和磁盘的空间浪费非常严重。特别是多进程操作系统情况下,静态链接极大浪费了内存空间。每个程序内部都保留了printf、scanf、strlen这样的公用库函数,还有数量相当可观的其他库函数以及它们所需要的辅助数据结构。

1.2 程序开发和发布

空间浪费是静态链接的一个问题,另一个问题是静态链接对程序的更新、部署和发布也会带来很多麻烦。比如程序Program1所使用的Lib.o是由第一个第三方厂商提供的,当该厂商更新了Lib.o的时候,那么Program1的厂商就需要拿到最新版的Lib.o然后将其与Program1.o链接后,将新的Program1整个发布给用户,这样做的缺点很明显,一旦程序中有任何模块更新,整个程序就要重新链接、发布给用户。

1.3 动态链接

要解决空间浪费和更新困难这两个问题最简单的方法是把程序的模块相互分割开来,形成独立的文件,而不再将它们静态链接在一起。简单来说就是不对那些组成程序的目标文件进行链接,而是等到程序要运行时才进行链接。把链接这个过程推迟到运行时再进行,这就是动态链接的基本思想。
在这里插入图片描述

在这里插入图片描述
上面的这种做法解决了共享的目标文件多个副本浪费磁盘和内存空间的问题,可以看到,磁盘和内存只存在一份Lib.o,而不是两份。另外在内存中共享一个目标文件模块的好处不仅仅是节省内存,它还可以减少物理页面的换入换出,也可以增加CPU缓存的命中率,因为不同进程间的数据和指令访问都集中在了同一个共享模块上。

上面的动态链接方案也可以使程序的升级变得更加容易,当我们要升级程序库或程序共享的某个模块时,理论上只要简单
在这里插入图片描述

在这里插入图片描述

程序可扩展性和兼容性

动态链接还有一个特点就是程序在运行时可以动态选择加载这种程序模块,这个特性后面被用来制作程序的插件。

动态链接还可以加强程序的兼容性,一个程序在不同的平台运行时可以动态地链接到由操作系统提供的动态链接库,这些动态链接库相当于在程序和操作系统之间增加了一个中间层,从而消除了程序对不同平台之间依赖的差异性。比如操作系统A和操作系统B对于printf的实现机制不用,如果我们的程序是静态链接的,那么程序需要分别链接成能够在A运行和在B运行的两个版本并且分开发布;但是如果是动态链接,只要操作系统A和操作系统B都能够提供一个动态链接库包含printf,并且这个printf使用相同的接口,那么程序只需要有一个版本,就可以在两个操作系统上运行,动态地选择相应的printf的实现版本。

动态链接的基本实现

动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有的程序都链接成一个单独的可执行文件。

动态链接设计运行时的链接及多个文件的装载,必须有操作系统的支持,因为动态链接的情况下,进程的虚拟地址空间的分布会比静态链接情况下更为复杂,还有一些存储管理、内存共享、进程线程等机制在动态链接下也会有一些微妙的变化。目前主流的操作系统几乎都支持动态链接方式,在Linux系统中,ELF动态链接文件被称为动态共享对象(DSO, Dynamic Shared Objects),简称共享对象,它们一般都是以.so为扩展名的一些文件。在Windows系统中,动态链接文件被称为动态链接库(Dynamic Linking Library),它们是以.dll为扩展名的文件。

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

程序与libc.so之间的链接工作是由动态链接器完成的,而不静态链接器完成的。
在这里插入图片描述

2 简单的动态链接例子

Windows平台下的PE动态链接机制与Linux下的ELF动态链接稍有不同,ELF比PE从结构上来看更加简单,接下来先以ELF为例描述动态链接过程,然后再单独描述Windows平台下PE动态链接机制的差异。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

动态链接程序运行时地址空间分布
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值