用户源程序从编辑到在内存中执行需要经历编译、链接和装入三个过程,如图3-2所示。编译就是将高级语言书写的源程序转换成目标计算机所能识别的指令,即生成目标模块。目标模块常常由于不完整而不可以独立运行。链接是将目标模块及所需要的库函数组装在一起,形成一个装入模块,通常指可执行程序。装入是将存储于外存的装入模块写入内存,准备执行。在现代操作系统中,程序的生成和运行大多是在集成开发环境中完成的,例如Visual C++6.0,用户可以使用它完成程序源代码的编辑、编译(Compile)、链接(Build)和运行(Run)。而装入过程包含在用户运行可执行程序的操作中,用户对此过程感受并不是很明显。
图3-2 用户程序处理过程
用户源程序经过编译,将得到一个或多个目标模块,其中有些目标模块并不依赖于任何其他目标模块,独自构成完整的程序,可以直接装入内存运行;有些目标模块依赖于其他目标模块,这些目标模块合在一起构成一个完整程序;有些模块除了依赖于其他目标模块外,还依赖于函数库,这些目标模块和函数库合在一起才能构成一个完整程序。目标模块的组合过程就是链接过程。根据目标模块的链接时机,可以把链接分成静态链接、装入时动态链接和运行时动态链接。
1.静态链接
程序运行之前,多个目标模块及所需的库函数链接成一个完整的装入模块存储于外存,以后不再拆分,我们把这种链接方式称为静态链接。很多集成开发环境都支持这种链接方式。例如,使用VC++6.0创建MFC AppWizard[exe]工程时,若要静态链接MFC库,可以在工程设置对话框的常规标签,Microsoft基础类下拉列表中选择“使用MFC作为静态链接库”。使用MFC作为静态链接库生成的可执行文件容量较大,但可以在任何Windows操作系统上运行,即使系统不包含MFC共享DLL库。
实现静态链接时,需解决一些问题。如图3-3所示,源程序经过编译得到三个目标模块A、B、C,它们的长度分别为0×20、0×50和0×30。目标模块A和目标模块B中分别定义了函数A()和函数B(),目标模块C中定义了一个全局变量m。函数A()调用函数B()通过跳转指令“jump B”实现,函数B()通过“storem,3”指令向全局变量m中存放了一个数值3。
图3-3 模块链接示意图
目标模块A、B、C链接时,由于函数名B及变量m都是外部调用符号,编译时地址处于待定,链接时必须解决两个问题。
(1)修改目标模块的相对地址
编译程序所产生的目标模块都有一个起始地址,一般为0,目标模块中的指令和数据地址都参照于这个起始地址计算。链接目标模块A、B、C时,目标模块B、C的起始地址不再是0,而分别是0×20和0×70。(www.xing528.com)
(2)变换外部调用符号
函数名及全局变量名均为外部调用符号,目标模块指令中的外部调用符号地址均处于待定状态。链接时待修改完目标模块的相对地址,外部调用符号地址确定下来后,需要对程序指令中的所有外部调用符号地址修正,即将目标模块A中的转移指令修正为“jump 0×20”,目标模块B中对全局变量m的数据存储指令修正为“store 0×80,3”。
2.装入时动态链接
目标模块在装入内存时,边装入边链接,即在装入一个目标模块时,如果发生其他模块调用,将引起装入程序查找相应的目标模块,并将此目标模块装入内存并进行链接。装入时动态链接方式有两个优点。
(1)便于目标模块的修改和更新
由于目标模块是独立存放,单个目标模块的修改和更新不会引起其他目标模块的改动,程序装入内存时仅需链接新的目标模块即可。而静态链接方式,单个目标模块的修改和更新会影响装入模块,需要目标模块重新链接生成新的装入模块。
(2)有利于实现目标模块的共享
静态链接方式生成的装入模块各自独立,自成一体,不存在目标模块共享。而对于装入时动态链接方式,装入模块可以在装入时共享相同的目标模块,实现多个程序对目标模块的共享。
3.运行时动态链接
运行时动态链接是在程序执行中,当发现某个被调用目标模块尚未链接,立即由操作系统去找到该目标模块并将之装入内存,再把它链接到调用目标模块上。运行时动态链接是对装入时动态链接的进一步改进,因为程序运行过程中无法预期目标模块的执行情况,在运行前就将所有的目标模块进行链接并装入内存,这样做显然是低效的。有些目标模块在本次运行根本不会被用到,例如,错误处理模块,还有程序中的大量分支结构注定有些目标模块是运行不到的。
综合考虑这三种链接方式,静态链接在程序运行前将其所依赖的所有目标模块组装在一起,外存上存放时会占用较多的存储空间,但是静态链接的程序相对独立,运行时不受约束。装入时动态链接只是将链接过程推迟到程序装入内存时刻,因此,程序在外存上存放时会占用较少的外存空间。运行时动态链接是当前最流行的链接方式,进一步推迟链接时机,该种方式下凡未被用到的目标模块都不会被调入内存和被链接到装入模块上,除了可以节省外存空间外,还可以减少不必要的链接工作,同时节省大量的内存空间。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。