70 年代的VAX 架构使用虚拟化线性页表的方式来实现分页。 VAX 将 32 位虚拟地址空间划分为四个范围:
- P0: 0x00000000 - 0x3fffffff。
- P1:0x40000000 - 0x7fffffff。
- S0: 0x80000000 - 0xbfffffff。
- S1:0xc0000000 - 0xffffffff。
P0(称为程序区)和P1(称为控制区)是用户特定的分区,S0是系统(内核)分区,S1是保留的。因此每个进程都有自己的一组 P0 和 P1 映射,但所有进程和内核共享相同的 S0 映射。
请注意,虚拟地址的最高两个有效位用于确定要访问虚拟内存的哪个部分。每个部分(S1 除外,它不可用)由页表定义。特别是P0和P1是由一个虚拟化的页表定义的(页表映射到虚拟内存),但是S0的页表没有被虚拟化。每个页表都是一个连续的 4 字节页表条目数组。每个页表条目要么无效,要么有效(这意味着它包含一个 512 字节页的物理地址)。
VAX 提供 6 个寄存器来定义页表:一个页表基地址寄存器和一个页表长度寄存器,分别用于虚拟地址空间 P0、P1 和 S0 的三个部分。 P0 和 P1 的基地址寄存器包含两个最高有效位为 10 的虚拟地址。即 S0 的页表包含包含 P0 和 P1 物理地址的页表条目。这允许任何进程的 P0 和 P1 的页表驻留在主存储器或辅助存储器中。另一方面,S0 的基地址寄存器包含 S0 的页表的物理地址。
所以本质上,一个进程的页表被划分为三个连续的页表,其中两个是虚拟化的,一个始终驻留在内存中。来自Wikipedia:
有人提到创建一个页表结构,其中包含
虚拟地址空间中每个虚拟页面的映射可能会结束
浪费。但是,我们可以绕过过多的空间问题
通过将页表放在虚拟内存中,并让虚拟
内存系统管理页表的内存。
但是,这种线性页表结构的一部分必须始终保持不变
常驻物理内存,防止循环页面
查找页表中不存在的关键部分的错误
在页表中,在页表中不存在,等等。
S0 的页表是线性页表的一部分,必须始终驻留在内存中(即未虚拟化)。但为什么一定要这样呢?如果 S0 的基地址寄存器包含虚拟地址而不是页表的物理地址会怎样?但是在那种情况下,处理器如何计算出页表的物理基地址呢?我们需要一些具有已知物理地址的附加数据结构,使我们能够找出页表的物理地址。为了论证,我们假设我们有这样一个存储在某个地方的数据结构。页表是否可以完全换出到辅助存储?是的,如果我们在该数据结构中有“当前位”或“有效位”之类的东西,我们就可以做到这一点。但是,当前位设置为假,在访问任何虚拟地址的内存时都会发生页面错误。操作系统现在需要处理页面错误,如果它需要访问任何虚拟地址,它将再次页面错误,依此类推。
否则,一般来说,如果页面错误处理程序设计为仅使用指向始终存在的数据和代码的物理地址(通过关闭分页),那么您可以有效地绕过虚拟化整个页表。但这会使处理程序的设计相当复杂。
将页表划分为多个连续数组,就像在 VAX 中所做的那样,意味着页表的某些部分(S0)必须始终存在。
但是如果 S0 的页表包含查找 P0 和 P1 的页表的条目,那么这不也是一个有效的多级页表吗?为了回答这个问题,让我们比较一下 VAX 和 32 位 x86 中的地址转换是如何完成的。
在VAX翻译中,虚拟页码与页表索引相同。
|31|29 9|8 0|
------------------------------------
| | virtual page number | offset |
------------------------------------
| | page table index | offset |
------------------------------------
在 32 位 x86 转换(禁用 PAE 和 PSE)中,虚拟页号被划分为两个索引,用于两级页表。
|31 12|11 0|
------------------------------------
| virtual page number | offset |
------------------------------------
| PT 1 index|PT 2 index| offset |
------------------------------------
在 VAX 中,只有对用户页表的访问需要两级查找。更重要的是,这两个查找是使用两个不同的虚拟地址执行的。另一方面,对系统页表的访问只需要使用单个虚拟地址进行一次查找。相比之下,在 x86 中,所有访问都需要使用相同的虚拟地址进行两级查找。
x86 架构支持虚拟化多级页表。
我们可以设计一个可能比两者都更强大的混合页表。如果我们使用 S1 分区作为第三个用户分区。我们可以为其表添加一个基地址寄存器,该寄存器包含物理地址而不是虚拟地址(如 P0 和 P1)。通过这种方式,即使是进程也可以获得线性页表的潜在性能优势,同时如果操作系统内存管理器需要,仍然允许虚拟化。不过,我不知道有任何架构使用过这种设计。