Alex_McAvoy

想要成为渔夫的猎手

程序的链接与装入

【程序链接与装入】

用户程序要在系统中运行,必须先将其装入内存,然后再将其转变为一个可执行的程序,通常要执行以下步骤:

  • 编译:由编译程序对用户源程序进行编译,形成若干个目标模块
  • 链接:由链接程序将编译后形成的一组目标模块及他们所需要的库函数链接在一起,形成一个完整的装入模块
  • 装入:由装入程序将装入模块装入内存

其中,在程序链接、装入的过程中,围绕着地址进行处理

【地址】

逻辑地址

逻辑地址又称相对地址虚地址,当用户的程序经过汇编或编译后形成的代码,目标代码中的指令地址即为相对地址

一般来说,逻辑地址首地址为 $0$,其余指令中的地址都相对于首地址来编址,需要注意的是,不能利用逻辑地址在内存中读取信息

物理地址

物理地址又称绝对地址实地址,内存中存储单元的地址即为实地址,其可以直接寻址被执行

地址映射

将用户程序中的逻辑地址转换为运行时机器直接寻址的内存物理地址的过程,称为地址映射

简单来说,地址映射,就将用户程序的第 $x$ 字节处的指令,转换为内存的第 $y$ 个地址上

【链接】

概述

源程序经过编译后,可得到一组目标模块

链接程序的功能是将这组目标模块及其所需要的库函数装配成一个完整的装入模块

在对目标模块进行链接时,根据进行链接的时间不同,可分为静态链接、装入时动态链接、运行时动态链接三种

静态链接

静态链接,是指在程序运行前,将各目标模块及其所需的库函数链接成一个完整的装配模块,以后不再拆开,其需要解决两个问题:

  • 对相对地址进行修改
  • 变换外部调用符号

装入时动态链接

装入时动态链接,是指讲用户源程序编译后所得的一组目标模块,在装入内存时,采用边装入边链接的方式

简单来说,在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去寻找相应的外部目标模块,并将他装入内存,同时,还要修改目标模块中的相对地址

装入时动态链接具有以下优点:

  • 便于修改、更新:相对于静态链接方式,如果要修改某个模块,需要重新打开装入模块进行修改,而采用装入时动态链接,由于各目标模块是分开存放的,因此要修改或更新十分方便
  • 便于实现对目标模块的共享:采用静态链接方式时,每个应用模块都必须含有其目标模块的拷贝,即 n 个程序就需要 n 次拷贝,但采用装入时动态链接的方式,OS 会十分容易将一个目标模块链接到几个应用模块上,从而实现多应用程序的共享

运行时动态链接

在许多情况下,应用程序在运行时,每次要运行的模块可能是不相同的,但由于实现无法知道本次要运行哪些模块,因此只能将可能要运行到的所有模块链接后装入内存,这无疑是低效的

比较典型的例子就是错误处理时的目标模块,如果程序在运行过程中不出现错误,那么这么模块将不会用到

运行时动态链接是对上述链接方式的一种改进,其将某些模块的链接推迟到程序执行时才进行

简单来说,在程序执行过程中,当发现一个被调用模块尚未装入内存时,立即由 OS 去找到该模块,将其链接到调用者模块上,并装入内存

【装入】

绝对装入方式

当计算机系统很小,且仅能运行单道程序时,完全有可能知道程序将驻留在内存的什么位置,此时可采用绝对装入方式

用户程序经编译后,将产生物理地址的目标代码,绝对装入程序便可按照装入模块中的地址,将程序与数据装入内存,装入模块被装入内存后,由于程序中的逻辑地址与物理地址完全相同,因此不需要对程序和数据的地址进行修改

绝对装入方式具有装入过程简单,不需任何地址变换,程序中的逻辑地址与实际内存物理地址完全相同等优点,但其过于依赖硬件结构,,只适用早期针对硬件直接编程、单道环境

静态可重定位装入方式

重定位是指将目标程序中的指令和数据的逻辑地址变成内存中的物理地址的地址变换过程。

静态可重定位装入方式是将逻辑地址经过重定位后,转为物理地址,再进行装入

地址映射在程序执行之前进行,重定位后物理地址不再改变,可由专门设计的重定位装配程序完成,在装入时根据所定位的内存地址去修改每个逻辑地址,添加相应偏移量,重定位为物理地址

静态可重定位装入方式不需硬件支持,可以装入有限的多道程序,但要求软件装入一次完成,这就造成一个程序通常需要占用连续的内存空间,程序装入内存后不能移动,也不易实现共享

动态运行时装入方式

在实际运行中,往往会需要程序在内存中的各位置移动,即经常需要将逻辑地址重定位到不同的物理地址上

这种运行时移动程序要求地址变换要快速,实现时一般依靠重定位寄存器来变换地址

动态运行时装入,可多次重定位到不同位置,即可以不将装入模块中的逻辑地址立刻转换为物理地址,而是把这种地址转换推迟到程序真正要执行时才进行

感谢您对我的支持,让我继续努力分享有用的技术与知识点!