Linux的x86-64用户虚拟地址空间为47位。这实际上意味着Linux可以映射具有大约~128 TB虚拟地址范围的进程。
然而,让我感到困惑的是x86-64架构支持每个进程的ISA定义的4级分层页表(排列为基数树)。页表的根目录最多只能映射512 GB的连续虚拟地址空间。那么Linux如何支持512GB以上的虚拟地址范围呢?它是否为每个进程使用多个页表?如果是,那么对于一个进程,CR3(x86-64的寄存器包含页表基址的地址)应包含哪个给定进程?我错过了什么吗?
答案 0 :(得分:7)
页表的根目录最多只能映射512 GB的连续虚拟地址空间。那么Linux如何支持512GB以上的虚拟地址范围呢?它是否为每个进程使用多个页表?如果是,那么对于一个进程,CR3(x86-64' s寄存器包含页表基址的地址)应包含哪个给定进程?我错过了什么吗?
我不知道你的意思是"页表的根目录",但x86-64上的分页看起来像这样:
512 * 4 KiB = 2 MiB
内存(它也可以作为2 MiB页面使用,但现在让它离开)。512 * 2 MiB = 1 GiB
内存(它也可以作为1 GiB页面,类似于PT)。512 * 1 Gib = 512 GiB
内存。512 * 512 GiB = 256 TiB
的记忆。我不知道Linux的确切内存映射,但可能更高的一半(从-128 TiB到0 - 从0xFFFF800000000000
到0xFFFFFFFFFFFFFFFF
)保留给内核,下半部分(从0到128 TiB - 从0x0000000000000000
到0x00007FFFFFFFFFFF
)用于用户空间应用程序。因此,Linux支持512倍于您要求的512 GiB虚拟地址范围;甚至Torvalds也不会说'#34;我们不会支持PML4"。我不知道是什么让你感到困惑 - 这是因为你错过了这个部分,说页面表映射了2个MiB而你已经把它当作一个页面映射 - 4 KiB - 但是如果有什么我可以澄清,问一下。
答案 1 :(得分:0)
通常不共享进程地址空间,这意味着所涉及的页表也不在不同进程之间共享。这意味着在所有4个表级别。
当然,公共(内核)部分总是存在于所有地址空间中,因此,事实上,存在一些共享,但内存只能由内核访问。
除此之外,实际上,每个进程都有自己的页表,并且在任何一个进程中使用所有2个 48 地址都没有任何问题。至少,CPU的部分没有特别限制,尽管可以有操作系统。