程序的装入与链接
# 程序的装入与链接
用户程序在执行前必须先进入内存,具体来说包括以下步骤:
- 编译:由编译程序将用户源程序编译成多个目标模块
- 链接:由链接程序将编译后的多个目标模块和所需的库函数链接在一起,形成一个总的装入模块
- 装入:由装入程序将装入模块装入内存运行
# 链接
根据链接的时间不同进行区分
# 静态链接
直接将编译后的多个目标模块和所需的库函数链接在一起,形成一个不再拆开的装入模块,该模块整体装入内存。
# 装入时动态链接
不事先进行链接,而是一边装入内存,一边进行链接,即在装入一个目标模块时,若发生一个外部模块调用事件,装入程序就去找出相应的外部目标模块。这种方式便于修改和更新,便于实现对目标模块的共享。
# 运行时动态链接
不事先进行链接,而是一边执行程序,一边进行模块的装入和链接,这种方式可以确保只装入和链接那些在执行时需要用到的模块,而不会引入多余的、实际根本用不到的模块,因此拥有装入时动态链接的优点,还加快了程序的装入过程,有利于节省内存空间。
# 装入
装入模块中指令所涉及的地址是逻辑地址(相对地址),往往并不是装入内存后的物理地址,因此在装入模块装入内存后,需要将原先的逻辑地址转换成物理地址(绝对地址)。在下面三种装入方式中,对逻辑地址的处理是不同的。
# 绝对装入方式
程序员如果事先知道程序最终装入内存时的物理地址(如在单道程序运行环境中),那么编译程序产生的目标模块中可以直接使用物理地址,此时的逻辑地址与物理地址一样,模块在装入到内存的时候也无需进行地址转换的工作。
# 静态重定位装入方式
在多道程序运行环境中,无法事先知道程序最终装入内存时的物理地址,所以目标模块中只能使用逻辑地址,所有指令中涉及到的逻辑地址都是从 0 开始的。装入模块可以装入到内存的合适位置,并且在装入的时候会进行地址转换(重定位)的工作。例如将程序中起始于 0 的逻辑地址都转换为起始于 10000 的物理地址。
“静态” 主要体现在程序装入内存后,在运行期间就不能再移动了,因为一旦移动就意味着需要再次更改物理地址,而地址是无法修改的,否则会发生错误。
# 动态重定位装入方式
很多时候,程序在内存中的位置会经常发生改变,比如在外存和内存之间对换。位置不会是一成不变的,这时候就要采用动态重定位装入方式。这种方式并不急于在装入的时候就进行地址转换,而是在程序真正执行的时候才去进行地址转换的工作。
这意味着程序在装入内存后,在运行期间是可以移动的。因为不管移动到哪个内存位置,始终会有一个重定位寄存器用于记录和更新装入模块当前的物理起始地址,逻辑地址只需要和这个物理起始地址相加即可得到物理地址。