Linux 中 x86-64 的用户虚拟地址空间为 47 位长。这本质上意味着 Linux 可以映射大约 128 TB 虚拟地址范围的进程。
然而,令我困惑的是,x86-64 架构支持 ISA 为每个进程定义的 4 级分层页表(排列为基数树)。页表的根最多只能映射 512 GB 的连续虚拟地址空间。那么Linux如何能够支持超过512GB的虚拟地址范围呢?每个进程是否使用多个页表?如果是,那么对于一个进程,CR3(x86-64 的寄存器,包含页表基地址)应该包含什么?我错过了什么吗?
页表的根最多只能映射 512 GB 的连续虚拟地址空间。那么Linux如何能够支持超过512GB的虚拟地址范围呢?每个进程是否使用多个页表?如果是,那么对于一个进程,CR3(x86-64 的寄存器,包含页表基地址)应该包含什么?我错过了什么吗?
我不知道“页表的根”是什么意思,但 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个指向PD的8字节条目(PDPTE);所以,PDPTE 描述
512 * 1 Gib = 512 GiB
的记忆。
- PML4,最高级别的分页结构,是包含指向 PDPT 的 512 个 8 字节条目(PML4E)的表;所以,PML4描述了
512 * 512 GiB = 256 TiB
的记忆。
我不知道 Linux 的确切内存映射,但可能是上半部分(从 -128 TiB 到 0 - 从0xFFFF800000000000
to 0xFFFFFFFFFFFFFFFF
)保留给内核,下半部分(从 0 到 128 TiB - 从0x0000000000000000
to 0x00007FFFFFFFFFFF
) 适用于用户空间应用程序。因此,Linux 支持您所要求的 512 GiB 虚拟地址范围的 512 倍;甚至 Torvalds 也不会说“我们不会支持 PML4”。我不知道是什么让您感到困惑 - 是不是您错过了说页表映射 2 MiB 的部分,而您却将其视为映射一页 - 4 KiB - 但如果有什么我可以澄清的,请询问它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)