为了更加有效地管理内存并减少出错,现代系统提供了虚拟内存(VM)的概念,它为每个进程提供了一个庞大、一致和私有的地址空间。

虚拟内存提供了三个重要能力:

  • 把主存看成一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据
  • 为每个进程提供一致的地址空间,从而简化了内存管理
  • 保护每个进程的地址空间不被其他进程破坏

1. 物理和虚拟寻址

早起的 PC 使用物理寻址,现代处理器使用虚拟寻址。虚拟寻址的方式需要内存管理单元(MMU)将虚拟地址转换为物理地址。

物理寻址
虚拟寻址

2. 地址空间

地址空间是一个非负整数地址的有序集合。如果地址空间中的整数是连续的,那么它就是线性地址空间。

在带有虚拟内存的系统中,CPU 从含有 N=2^n 个地址的地址空间中生成虚拟地址,称为虚拟地址空间。

系统还有一个物理地址空间,对应物理内存的 M 个字节。

地址空间清楚地区分了数据对象(字节)和它们的属性(地址)。允许每个对象有多个独立的地址,其中每个地址都选自不同的地址空间,这就是虚拟内存的基本思想。主存中的每个字节都有一个来自虚拟地址空间的虚拟地址和来自物理地址空间的物理地址。

3. 虚拟内存作为缓存的工具

虚拟内存被组织为一个由存放在磁盘上的 N 个连续的字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,作为到数组的索引。磁盘上数组的内容被缓存在主存中。

虚拟内存被分割为称作虚拟页(VP)的大小固定块,来作为磁盘和主存之间的传输单元。类似地,物理内存被分割为物理页。在任意时刻,虚拟页面的集合都分为三个不相交的子集:未分配的、缓存的、未缓存的。

页表(page table)将虚拟页映射到物理页。每次 MMU(内存管理单元)中的地址翻译硬件将虚拟地址转换为物理地址时,都会读取页表。
操作系统负责维护页表的内容,以及在磁盘与 DRAM 之间来回传送页。

页表

页表就是一个页表条目(PTE)的数组。虚拟地址空间中的每个页在页表中一个固定偏移量处都有一个 PTE。

DRAM 缓存不命中称为缺页(page fault)。缺页会触发缺页异常,该异常调用缺页异常处理程序,该程序会选择一个牺牲页,
内核总会修改牺牲页的页表条目,牺牲页就不再缓存在主存中。当异常处理程序返回时,它会重新启动导致缺页的指令,
该指令会把导致缺页的虚拟地址发送到地址翻译硬件,页命中就能由地址翻译硬件正常处理了。

在磁盘和内存之间传送页的活动叫做交换(swapping)或者页面调度(paging)。页从磁盘换入 DRAM 和 从 DRAM 换出磁盘。
当有不命中发生时才换入页面的策略叫做按需页面调度(demand paging)。所有现在操作系统都是用按需页面调度的方式。

尽管在整个运行过程中程序引用的不同页面的总数可能超出物理内存总的大小,但是局部性原理保证了在任意时刻,
程序将趋于在一个较小的活动页面(active page)集合上工作,这个集合叫做工作集合。

如果工作集的大小超出了物理内存的大小,那么程序将产生一种不幸的状态,叫做抖动(thrashing),这时页面将不断地换进换出。

4. 虚拟内存作为内存管理的工具

实际上,操作系统为每个进程提供了一个独立的页表,也就是一个独立的虚拟地址空间。注意,多个虚拟页面可以映射到同一个共享的物理页面上。

内存管理

5. 虚拟存在作为内存保护的工具

提供独立的地址空间使得区分不同进程的私有内存变得容易。地址翻译机制可以通过一种自然的方式扩展到提供更好的访问控制。CPU 每次生成一个地址时,地址翻译硬件都会读一个 PTE。所以可以通过在 PTE 上添加一些额外的许可位来控制一个虚拟页面内容的访问。

内存保护