Linux x86-64 的用户虚拟地址空间是 47 位长。这实质上意味着 Linux 可以映射具有大约 128 TB 虚拟地址范围的进程。
然而,让我感到困惑的是,x86-64 架构支持 ISA 为每个进程定义的 4 级分层页表(排列为基数树)。页表的根最多只能映射 512 GB 的连续虚拟地址空间。那么Linux如何支持超过512GB的虚拟地址范围呢?它是否为每个进程使用多个页表?如果是,那么对于一个进程,对于任何给定的进程,CR3(x86-64 的寄存器包含页表基址的地址)应该包含什么?我错过了什么吗?
最佳答案
The root of the page table can only map up to 512 GB of contiguous virtual address space. So how Linux can support more than 512GB of virtual address range? Does it uses multiple page tables for each process? If yes, then for a process what should the CR3 (x86-64's register to contain the address of the base of the page table) contain for any given process? Am I missing something?
我不知道“页表的根”是什么意思,但 x86-64 上的分页看起来像这样:
- 页表 - 最低级别的分页结构。每个都有 512 个 8 字节条目 (PTE),描述一个 4 KiB 页面,因此 PT 描述
512 * 4 KiB = 2 MiB
内存(它也可以用作 2 MiB 页面,但让我们把它留给现在)。 - 页目录 - 表,类似于 PT,包含 512 个 8 字节条目 (PDE) 指向 PT;因此,PD 描述了
512 * 2 MiB = 1 GiB
内存(它也可以作为 1 GiB 页面工作,类似于 PT)。 - 页目录页表 - 类似于 PD,但包含 512 个 8 字节条目 (PDPTE) 指向 PD;因此,PDPTE 描述了
512 * 1 Gib = 512 GiB
内存。 - PML4,最高级别的分页结构,是包含指向 PDPT 的 512 个 8 字节条目 (PML4E) 的表;因此,PML4 描述了
512 * 512 GiB = 256 TiB
内存。
我不知道 Linux 的确切内存映射,但可能较高的一半(从 -128 TiB 到 0 - 从 0xFFFF800000000000
到 0xFFFFFFFFFFFFFFFF
)是为内核保留的,下半部分(从 0 到 128 TiB - 从 0x0000000000000000
到 0x00007FFFFFFFFFFFF
)用于用户空间应用程序。因此,Linux 支持您要求的 512 GiB 虚拟地址范围的 512 倍;甚至 Torvalds 也不会说“我们不会支持 PML4”。我不知道是什么让你感到困惑 - 是不是你错过了说页表映射 2 MiB 的部分并且你已经把它映射了一页 - 4 KiB - 但如果有什么我可以澄清的,请询问
关于linux - Linux 如何在 x86-64 中支持超过 512GB 的虚拟地址范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11246559/