本章介绍的是如何设计进程的虚拟地址空间,并且提出了几个待解决的问题: 1. 如何使虚拟地址高效。 2. 如何实现应用程序的复杂的功能需求。 3. 操作系统如何完整地掌握对内存的控制权。 4. 严格限制进程对内存的访问。

要实现这四个需求,就如同虚拟 CPU 一样,需要硬件的支持。也就是 hardware-based address translation: 将程序中的虚拟地址空间翻译成进程在内存中的真实地址

和虚拟 cpu 一样,首先提出三个假设。 1. 进程的内存空间在物理内存中是连续的。 2. 进程的内存空间大小不会超过物理内存。 3. 进程的内存空间大小是相同的。

0KB +----------------+
    |  Program Code  |
2KB +----------------+
    |      Heap      |
4KB +----------------+
    |                |
    |                |
    |                |
    |                |
    |      Free      |
    |                |
    |                |
    |                |
    |                |
14KB+----------------+
    |     Stack      |
16KB+----------------+

对于一个程序来说,地址空间应该是从零开始增长的。但是,在物理内存中,是多个进程共享同一个物理内存,并且操作系统需要占用从零开始的空间,所以实际上进程在物理内存中被分配的地方并不是从零开始的,也就是说可能是内存中的任意一个地方。所以,需要有一套机制,来实现虚拟地址和物理地址之间的转换

Dynamic Relocation

这个也叫做 Hardware Based Relocation。这要求 CPU 提供两个寄存器,一个是 base,一个是 bounds。

base 存储的是当前进程在内存中的首地址。程序在编译的时候感知到的是从零开始的,那么物理地址就是 base 和 虚拟地址的和。也就是 phisical address = virtual address + base。这样程序便只知道自己的虚拟地址,而不用去关心物理地址了。

bounds 寄存器存储的是存储虚拟空间最大地址的。如果虚拟地址大于 bounds,就会触发一个异常。这么做是为了防止程序越界访问其它进程的地址空间。这两个寄存器只有在内核态才可以被修改。cpu 同时会记录目前的状态是内核态还是用户态。也就是只有操作系统才能够变更这两个寄存器的值。

OS Issues

对于操作系统来说,它必须要能够有这样一些能力。 1. 当一个程序开始运行,操作系统要在内存中寻找空余空间来提供给这个进程。 2. 当进程被终止,操作系统需要回收这些内存,使其能够在后面的进程运行的时候可以被使用。 3. 当进程在上下文切换的时候,进程要能够变更这一对寄存器的值。 4. 操作系统提供了异常处理函数来处理进程操作内存不当而引发的异常。