9.3节从缓存的角度介绍了虚拟内存。

虚拟内存被组织为一个由存放在磁盘上连续字节大小的单元组成的数组,磁盘上数组的内容被缓存在主存上。

虚拟内存被分割为虚拟页,和存储器层次结构中,低层级存储器上的数据被分割成块,向高等级存储器发送的一般规律呼应。

任意时刻,虚拟页这个大集合存在如下的划分(遵照严格的划分定义):

  1. 未分配页:虚拟内存中未分配/创建的页,不占用空间。
  2. 已缓存页:已缓存在物理内存中的已分配页。
  3. 未缓存页:已经分配,但内容并未缓存到主存的虚页。

DRAM缓存因不命中开销巨大(牵涉硬盘的读写),故虚拟内存有以下特点:

  1. 虚页大小相对较大,一般是4KB-2MB。
  2. DRAM缓存是全相连的,即任何虚拟页都可能和任何物理页产生对应关系。
  3. 不命中的替换算法至关重要。(CSAPP对这点未深入讨论,这算是专门的OS教科书应该涉及的内容)
  4. DRAM写操作总是采用写回,而不是直写策略。(形象说就是lazy evaluation)

页表:

必要性:虚拟内存系统必须有某种办法判定一个虚页是否已经被DRAM缓存。如果命中,又需要确定虚页和物理页的对应关系。如果不命中,系统需要判断虚页和磁盘位置的对应关系,从物理内存选择牺牲页,将虚拟页对应的磁盘内容复制到DRAM,替换牺牲页。

页表的单元是页表条目。本节的讨论中把一个条目视作由一个隐含的固定偏移量、有效位、一个地址字段组成。

有效位表示该虚拟页是否已被DRAM缓存。设置了有效位,则地址字段表示物理页的起始地址。未设置有效位,则一个NULL表示虚拟页未被分配。否则地址指向虚拟页再磁盘上的起始位置。

页命中:欲查询的虚拟地址对应的页表条目有效位被设置。地址翻译硬件将虚拟地址作为索引,构造出对应的物理地址,定位主存中的数据,并进行读取。

缺页:欲查询的虚拟地址对应的页表条目有效位为0。此时,触发一个缺页异常,控制流移交给操作系统内核的缺页异常处理程序。该程序通过一定的算法选择被牺牲页。如果该被牺牲页在载入内存后被修改,则把页中的内容复制回磁盘,否则可以直接牺牲。注意,无论是否发生向磁盘的复制,该页表条目都已经不再对应先前页的数据。

之后,内核从磁盘复制欲查询的虚拟地址对应的磁盘数据到内存,更新页表条目。然后控制六换回到导致缺页异常触发的指令。此时执行即是页命中的情况。

虚拟内存的解决方案之所以在实践中展现出了违反直觉的高效性,其原因还是可以从局部性中寻找。谈论虚拟内存时,经常被引用的数据集被称为工作集或常驻集合。