不同的进程有不同的地址空间页表。
Linux内核有自己的页表吗?如果不是,内核的虚拟地址如何转换为物理内存地址?
从每个进程的地址空间分为用户空间和内核空间的意义上来说,每个进程的页表是否包含内核的“页表”?
谢谢。
答案1
你是对的。进程的VM由用户地址空间和内核地址空间组成。所有进程的内核地址空间都是相同的,但受到保护以防止访问。如果您听说过 2/2 或 3/1 内存分割(从 x32 开始),那么它就是用户/内核的内存量(以 GB 为单位)。因此,对于 4GB 地址空间,您可以(例如)为进程分配 3G,为内核分配 1G。
我建议您阅读《Understanding the Linux Kernel》一书,它将回答这个问题以及您的许多其他问题。
答案2
“页表”实际上是一种树结构。例如,参见《四级页表》[LWN.net,2004]。
顶层是单页(4096 字节)。映射内核范围的条目在所有进程中设置为相同的值,因此是共享的。内核临时映射发生在树的较低级别,因此它们只需要修改共享内核页表内部,而不需要单独修改每个进程页表。
至少,这是我的总体概述。我没有所有的话。
以上内容是从我的回答中交叉发布的:https://unix.stackexchange.com/a/513184/29483
答案3
我有同样的问题,并想分享我的发现 - 它因计算机体系结构而异。
ARM处理器- 可以支持两个不同的表。
简而言之,有 2页表基址寄存器另一个控制寄存器用于分割地址空间。其中一个 PTBR 可用于内核,而另一个可用于正在运行的用户进程。 ARM 调用这些寄存器: TTBR1/TTBR2(转换表基址寄存器)和 TTBCR(转换表基址控制寄存器)
x86 处理器- 不提供(硬件)支持。 x86 处理器仅具有CR3保存当前页表地址的寄存器。
然而,内核页表的重复仅真正存在于页表目录的第一级中的每个进程。一个虚拟地址(在顶级页表中)的内核部分的所有虚拟页表条目都将指向相同的2级页表作为其他进程的顶级页表。
意思:仅一半顶级页表(其设计为最多单个页框)实际上是重复的。
这也与 2018 年发布的 Meltdown 安全漏洞有关。由于内核页表被映射到每个虚拟地址空间,因此出现在每个进程的页表中,因此竞争条件允许用户空间代码读取可从该进程的页表访问的任何内存。页表(即内核内存)。解决办法是实施内核页表隔离:
KPTI 通过完全分离用户空间和内核空间页表来修复这些泄漏。一组页表包括与以前相同的内核空间和用户空间地址,但仅在系统运行在内核模式下时使用。用于用户模式的第二组页表包含用户空间的副本和最小的内核空间映射集,该映射提供进入或退出系统调用、中断和异常所需的信息。
答案4
这是一个有趣的问题,我也很好奇。我将尝试在以下条件下回答这个问题:
- 内核版本5.10.7
- 拱门x86
CONFIG_PGTABLE_LEVELS
为 2(使用二级页表)- 内核地址空间为1G
对于每个进程来说,第一级页表称为“页全局目录”,或pgd
。条目索引#768 到索引#1023pgd
用于映射内核地址。每个进程都有自己唯一的 4K 字节页面,用于pgd
.是的,对于你的问题,从 #768 到 #1023 的条目pgd
是相同的,并且每个进程都会重复。但这只是很小的一部分。内核的二级页表仍然在所有进程之间共享。
请参考arch/x86/mm/pgtable.c
函数pgd_ctor()
来了解第一级页表(pgd)的重复部分是如何创建的。