1、加载和链接创建一个活跃进程的第一步是把程序装入主存,并创建一个进程映像。下图描述了大多数系统中的一种典型情况。应用程序由许多已编译/汇编过的模块组成,这些模块以目标代码的形式存在,它们被链接起来以解释模块间的任何访问,同时还解析到库例程的访问。库例程自己可以合并到程序中,或作为操作系统在系统运行时提供的共享代码被访问。加载下图中,加载器把加载的模块放置在主存中从 x 单元开始处。在加载这个程序的过程中,必须满足图 7.1 描述的寻址要求。程序数据目标代码程序数据栈PCB主存中的进程映像图 7.13 加载功能该图描述了一个进程映像。为简单起见,假设这个进程映像占据了主存中的一段相邻区域。显然操作
2、系统需要知道进程控制信息和执行栈,以及为这个进程开始执行程序的入口点的位置。由于操作系统负责管理存储器并负责把该进程取进主存,因而可以很容易地得到这些地址。此外,处理器必须处理程序内部的存储器访问。分支指令包含下一步将要执行的指令地址,数据访问执行包含访问数据的字节或字的地址。由于某种原因,处理器硬件和操作系统必须能够把程序代码中的存储器访问转换成实际的物理存储器地址,以反映出程序在主存中的当前位置。一般而言,可以采用三种方法:绝对加载;可重定位加载;动态运行加载绝对加载一个绝对加载器要求一个给顶的加载模块总是被加载到主存中的同一个单元,因此在提供给加载器的加载模块中,所有的地址访问必须是确定
3、的,或者说是绝对的主存地址。如图7.14,x 是 1024 单元,加载模块中的第一个字在主存中的地址也为 1024。给程序中的存储访问指定具体的地址值,可以由程序员完成,也可以在编译/汇编时完成(表 7.2a) 。第一种方法存在缺点:程序员必须知道在主存中放置模块时预定的分配策略;如果对程序做任何修改,且涉及在模块体中增加/删除代码,则所有地址都需要更改。因此更可取的方法是允许用符号表示程序中的存储器访问,然后在编译/汇编时解析这些符号引用。如图 7.15。对指令或数据项的引用最初被表示成一个符号,在准备输入到一个绝对加载器的模块,汇编/编译器将把所有这些引用转换成具体地址。表 7.2a 地址
4、绑定(加载器)绑定时间 功能程序设计时编译或汇编时加载时运行时程序员直接在程序中确定实际的物理地址程序包含符号地址访问,由编译/汇编器把它们转换成实际的物理地址编译/汇编器产生相对地址,加载器在加载程序中把它们转换成实际的绝对地址被加载的程序保持相对地址,处理器硬件把它们动态地转换成绝对地址库存储器模块#1模块#2模块#n存储器x链接器加载模块加载器7.14 一个加载方案可重定位加载在加载之前就把存储器访问绑定到具体的地址,其缺点是使得加载模块只能放置在存储器中的一个区域。当多个程序共享主存时,不可能事先确定哪块区域用于加载哪个特定的模块。最好能在加载时确定。为满足这个新要求,汇编/编译器不产
5、生实际的主存地址(绝对地址) ,而是相对于某些已知点的位置,如相对于程序的起点。如图 7.15c 所示。加载模块的起点被指定为相对地址 0,模块中的所有其他存储器访问都相对于该模块的起点来表示。既然所有存储器访问都以相对的形式表示,加载器就可以很容易地把模块放置在期望的位置。如果该模块要加载到从 x 单元开始的地方,则当加载器把模块加载到主存中时,必须简单地被每个存储器访问都加上一个 x。为此,加载模块必须向加载器提供一些信息:地址访问在哪里、如何被解释(相对于程序起点/当前位置)等,这些信息由编译/ 汇编器产生,通常称作重定位字典。动态运行时加载多道程序环境中,即便不依赖于虚存,可重定位加载
6、方案仍是不够的。进程需要换入/出主存,以增大处理器的利用率。为最大限度地利用处理器,我们希望能在不同时候将一个进程映像换回到不同地方。因此,程序一旦被加载,就可能被换出内存,然后又换回到不同位置。如果开始加载时,存储器访问就被绑定到绝对地址,则不可能以上要求。可选择的一种方法是把绝对地址的计算推迟到运行中真正需要时。为此,加载模块被加载到主存,它的所有存储器访问都以相对形式表示(图 7.15c) ,只有一个指令真正被执行时计算绝对地址。这些工作由特殊的处理器硬件完成。链接链接器的功能是把一组目标模块作为输入,产生一个包含完整的程序和数据模块的加载模块,传递给加载器。每个目标模块中,可能有其他模
7、块的地址访问,这个这样的访问在未链接的目标模块中用符号表示。链接器创建一个加载模块,它是所有目标模块相邻的链接。每个模块内的访问必须从一个符号地址转换成对整个加载模块中的一个单元的访问。例如图 7.16a 中的模块 A 包含对 B 的一个过程调用,当这些模块都组合到加载模块中时,这个YX程序JUMP XLOAD Y数据符号地址a. 目标模块222410241424程序JUMP 1424LOAD 2224数据绝对地址b. 绝对加载模块01200400程序JUMP 400LOAD 1200数据相对地址c. 相对加载模块图 7.15 绝对和可重定位加载模块到模块 B 的符号访问就变成了对加载模块中
8、B 的入口点处单元的一个具体访问。链接编辑程序这个地址链接的性质取决于连接发生时要创建的加载模块的类型(表 7.2b) 。如果需要一个可重定位的加载模块,链接可按以下方式完成。每个已编译/汇编过的目标模块连同相对于该目标模块开始处的引用一同被创建。所有这些模块,连同相对于该加载模块起点的所有引用,一起放在一个可重定位的加载模块中。该模块可用于重定位加载或动态运行时加载的输入。一个产生可重定位加载模块的链接器通常称作链接编辑程序。图 7.16 显示了链接编辑程序的功能。在加载时可能会推迟某些链接功能。动态链接(dynamic linking)指把某些外部模块的链接推迟到创建加载模块之后,因此加载模块包含到其他程序的未解析的引用,这些引用可在加载/运行时被解析。加载时的动态链接采取以下步骤:把被加载的加载模块(应用模块)读入存储器,到一个外部模块的任何引用都导致加载程序查找目标模块,加载,并把这些引用修改成相对于应用程序模块开始处的相对地址。模块 A调用 B;返回长度 L模块 B调用 C;返回长度 M模块 C返回长度 Na. 目标模块L-+M+N-1L+M-1L+ML-1L0 模块 AJSR” L ”返回模块 BJSR “ L+M ”返回模块 C返回相对地址 b. 加载模块图 7.16 链接功能