Memory Management

一、

基本硬件

CPU 内置寄存器通常可以在一个CPU 时钟周期内完成访问。 对于寄存器中的内容, 绝大多数 CPU 可以在一个时钟周期内解析并执行一个或多个指令, 而对于内存(其访问通过内存总线上的事务进行)就不行了。 完成内存访问可能需要多个CPU 时钟周期, 由于没有数据以便完成正在执行的指令,CPU 通常需要暂停 (stall)。由于内存访问频繁, 这种情况是难以忍受的。 解决方法是在CPU与内存之间, 增加高速内存。 这种协调速度差异的内存缓存区, 称为高速缓存(cache)。

首先需要确保每个进程都有独立的内存空间。 为此,需要确定进程可访问的合法地址的范围, 井确保进程只访问其合法地址。基地址寄存器( 含有最小的合法物base register)理内存地址,而界眼地址寄存器 (limit register) 决定了范围的大小。

如果用户模式下执行的程序试图访问操作系统内存或其他用户内存, 则会陷入到操作系统,并作为致命错误处理

只有操作系统可以通过特殊的特权指令来加载基地址寄存器和界限地址寄存器。由于特权指令只可在内核模式下执行,而只有操作系统在内核模式下执行,所以只有操作系统 可以加载基地址寄存器和界限地址寄存器。这种方案允许操作系统修改这两个寄存器的值, 而不允许用户程序修改它们。

地址绑定

如果在编译时就知道进程将在内存中的驻留地址,那么就可以生成绝对代码 (absolute code) 。例如,如果事先就知道用户进程驻留在内存地址 R ,那么所生成的编译代码就可以从该位置开始并向后扩展。如果将来开始地址发生变化,那 么就必须重新编译代码。 MS-DOS 的 .COM 格式程序就是在编译时绑定成绝对代码的。

1

加载时(load time):如果在编译时并不知道进程将驻留在内存的什么地方,那么编译器就必须生成可重定位代码 (relocatable code) 。对于这种情况,最后绑定会延迟到加载时才进行。如果开始地址发生变化,只需重新加载用户代码以引入改变值。

执行时(execution time): 如果进程在执行时可以从一个内存段移到另一个内存段, 那么绑定必须延迟到执行时才进行。正如 8. 1. 3 小节所述,采用这种方案需要特定的硬件。 绝大多数通用计算机操作系统采用这种方法。

逻辑地址空间与物理地址空间

CPU 所生成的地址通常称为逻辑地址( logical address) ,而内存单元所看到的地址即加载到内存地址寄存器 (memory-address register) 中的地址)通常称为物理地址 (physical address) 。

由程序所生成的所有逻辑 地址的集合称为逻辑地址空间 (logical address space) ,与这些逻辑地址相对应的所有物理 地址的集合称为物理地址空间(physical address space)。、

运行时从虚拟地址到物理地址的映射是由被称为内存管理单元(memory-management unit , MMU) 的硬件设备未完成的逻辑地址空间绑定到单独的一套物理地址空间这一概念对内存的管理至关重要。

基地址寄存器在这里称为重定位寄存器( relocation register)。用户进程所生成的地址在送交内存之前,都将加上重定位寄存器的值。

动态加载

迄今为止所讨论的是一个进程的整个程序和数据必须处于物理内存中,以便执行。因此进程的大小受物理内存大小的限制。为了获得更好的内存空间使用率,可以使用动态加 载 (dynamic loading) 。采用动态加载时,一个子程序只有在调用时才被加载。所有子程序都以可重定位的形式保存在磁盘上。动态加载的优点是不用的子程序决不会被加载。

动态链接

动态链接的概念与动态加载相似。只是这里不是将加载延迟到运行时,而是将链接延迟到运行时。这一特点通常用于系统库,如语言子程序库。没有这一点,系统 上的所有程序都需要一份语言库的副本(或至少那些被程序所引用的子程序)。这一要求浪费了磁盘空间和内存空间。

二、

交换

进程需要在内存中以便执行。不过,进程可以暂时从内存中交换 (swap) 到备份存储 (backing store) 上,当需要再次执行时再调回到内存中。当更高优先级的进程执行完后,低优先级进程可以交换回内存以继续执行。这种交换有时称为滚出 (roll out) 和滚入 (roll in) 。

通常,一个交换出的进程需要交换回它原来所占有的内存空间。这一限制是由地址绑定方式决定的。如果绑定是在汇编时或加载时所定的,那么就不可以移动到不同的位置。 如果绑定在运行时才确定,由于物理地址是在运行时才确定的,那么进程可以移到不同的地址空间。

知道一个用户进程所真正需要 的内存空间, 而不是其可能需要的内存空间,是非常有用的。 这样,只需要交换真正使用的内存, 以减少变换时间。 为有效使用这种方法, 用户需要告诉系统其内存需求情况。 因此, 具有动态内存需求的进程要通过系统调用(请求内存和释放内存)来通知操作系统 其内存需求变化情况。

三、

采用连续内存分配( contiguous memory allocation) 时,每个进程位于一个连续的内存区域。

MMU 动态地将逻辑地址加上重定位寄存器的值后映射成物理地址。映射后的物理地址再送交内存单元。

当 CPU 调度器选择一个进程来执行时,作为上下文切换工作的一部分,调度程序会用 正确的值来初始化重定位寄存器和界限地址寄存器。