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