我们知道,程序要执行,必须被CPU调用执行,而前提是装入到主存中。所以程序的装入对于操作系统来说,是一件非常重要的工作。要了解程序是如何装入到主存中,我们首先来了解下逻辑地址和物理地址。
主存的存储单元以字节为单位编址,每个存储单元都有一个地址与其对应。假定主存的容量是256M,即256*1024*1024=2^28个字节(256M=256*2^10K=256*2^10*2^10B),则该主存就有2^28个字节的存储空间,起地址编号为0,1,2,…………2^28-1。这些地址称为主存的物理地址(也称为绝对地址),物理地址对应的主存空间称为物理地址空间;然而,在多道程序设计系统(如windows,linux等)中,主存中同时存放了多个用户作业。每次调入运行时,操作系统将根据主存的使用情况为用户分配主存空间,每个用户不可能预先知道其作业存放的主存的具体位置(物理位置)。因此,在用户程序中不能使用主存的物理地址。为了方便程序的编制,每个用户可以认为自己作业系统和数据存放在一组从0地址开始的连续空间中。用户程序所使用的地址称为逻辑地址(也叫相对地址或虚地址),逻辑地址对应的存储空间成为逻辑地址空间。
下面我们来开始看看程序载入的一般步骤:编译-链接-装入。首先编译,有编译程序(Complier)将用户源代码编译城若干目标模块(Object
Module)(.obj文件);然后链接,有连接程序(Linker)将编译后形成的一组目标以及它们所需要的库函数链接在一起,形成一个完整的装入模块(Load
Module)(如.exe文件);最后装入,由装入程序(Loader)将装入模块装入主存。看下图
将一个装入模块装入主存中,有3种方法:绝对装入方式,
静态重定位装入方式, 动态重定位装入方式。
1:绝对装入方式。如果在编译时就知道了程序驻留在主存的具体位置,则编译程序将产生的物理地址的目标代码。绝对装入程序按照装入模块的地址,将程序和数据装入主存。模块装入后,由于程序中的逻辑地址和实际主存的地址完全相同,
所以不需要修改程序和数据的地址。
但是,如果要程序猿直接给出程序和数据的物理地址,则要求比较高,不但要求程序猿熟悉主存的使用情况,而且一旦要修改某个地址,就可能要修改程序中所以地址,所以在程序中往往使用符号地址,在编译或汇编时将其转换为物理地址。
注意事项:绝对装入方式只能将目标模块装入到主存事先指定的固定位置,只适用于单道程序环境。看下图。
2:静态重定位装入方式。在装入作业时,把该作业中的指令指令和数据地址一次性全部转换为物理地址,这样在作业执行过程中无需再进行地址转换工作,这种地址转换方式称为静态重定位,这种作业装入方式称为静态重定位装入方式。如图。
3:动态重定位装入方式。在装入作业时,装入程序直接把作业装入到所分配的主存区域中。在作业执行过程中,随着每条指令或数据的访问,由硬件地址转换机制自动地将指令中的逻辑地址转换称对应的物理地址。这种地址转换的方式是在作业执行的过程中动态完成的,所以叫动态重定位。如图。
注意,动态定位由硬件(基地址寄存器)和软件相互配合实现。
采用动态重定位,由于装入主存的作业仍保持逻辑地址,所以,必要时可改变作业在主存中的存放区域。若改变了存储区域,作业仍能正确执行,则称程序是可浮动的。采用动态重定位的系统支持程序浮动(碎片整理时用到)。而静态重定位由于装入主存时作业信息都已转化为物理地址,执行过程中不再进行地址转换,所以作业执行过程中不能改变存放位置,即采用静态重定位的系统不支持程序浮动。
PS——参照机械工业出版社《操作系统教程》.
图片来自Google Images.