6

x86-64 与 Linux 的用户虚拟地址空间是 47 位长。这实质上意味着 Linux 可以映射一个具有大约 128 TB 虚拟地址范围的进程。

然而,令我困惑的是 x86-64 架构支持 ISA 为每个进程定义的 4 级分层页表(排列为基数树)。页表的根最多只能映射 512 GB 的连续虚拟地址空间。那么Linux如何能够支持超过512GB的虚拟地址范围呢?它是否为每个进程使用多个页表?如果是,那么对于一个进程,对于任何给定进程,CR3(x86-64 的包含页表基地址的寄存器)应该包含什么?我错过了什么吗?

4

2 回答 2

8

页表的根最多只能映射 512 GB 的连续虚拟地址空间。那么Linux如何能够支持超过512GB的虚拟地址范围呢?它是否为每个进程使用多个页表?如果是,那么对于一个进程,对于任何给定进程,CR3(x86-64 的包含页表基地址的寄存器)应该包含什么?我错过了什么吗?

我不知道“页表的根”是什么意思,但是 x86-64 上的分页看起来像这样:

  • 页表 - 最低级别的分页结构。每个都有 512 个 8 字节条目 (PTE) 描述一个 4 KiB 页面,因此 PT 描述512 * 4 KiB = 2 MiB了内存(它也可以用作 2 MiB 页面,但我们现在暂且不谈)。
  • 页面目录 - 类似于 PT 的表,包含 512 个指向 PT 的 8 字节条目 (PDE);因此,PD 描述512 * 2 MiB = 1 GiB了内存(它也可以作为 1 GiB 页工作,类似于 PT)。
  • 页面目录页表——类似于 PD,但包含 512 个指向 PD 的 8 字节条目(PDPTE);因此,PDPTE 描述512 * 1 Gib = 512 GiB了内存。
  • PML4 是最高级别的分页结构,是包含 512 个 8 字节条目 (PML4E) 的表,指向 PDPT;因此,PML4 描述512 * 512 GiB = 256 TiB了内存。

我不知道 Linux 的确切内存映射,但可能上半部分(从 -128 TiB 到 0 - from 0xFFFF800000000000to 0xFFFFFFFFFFFFFFFF)保留给内核,下半部分(从 0 到 128 TiB - from 0x0000000000000000to 0x00007FFFFFFFFFFF)用于用户空间应用程序。因此,Linux 支持的虚拟地址范围是您所要求的 512 GiB 的 512 倍;甚至 Torvalds 也不会说“我们不会支持 PML4”。我不知道是什么让你感到困惑 - 是不是你错过了说页表映射 2 MiB 的部分,而你把它当作它映射一页 - 4 KiB - 但如果有什么我可以澄清的,请询问它。

于 2012-06-28T14:55:32.130 回答
0

通常进程地址空间不共享,这意味着所涉及的页表也不在不同进程之间共享。这意味着在所有 4 个表级别。

当然,公共(内核)部分始终存在于所有地址空间中,因此,实际上存在一些共享,但那里的内存只能由内核本身访问。

除此之外,实际上,每个进程都有自己的页表,并且在其中任何一个中使用所有 2 48 个地址都没有任何问题。至少,在 CPU 方面没有特别的限制,虽然在操作系统方面可以有。

于 2012-06-28T14:28:32.113 回答