linux-kernel - Linux 进程地址空间中的最后 GB 是否映射到相同的物理内存?

标签 linux-kernel virtual-address-space

我读到前 3 GB 是为进程保留的,最后 GB 是为内核保留的。我还了解到内核是从物理地址空间的第 2 MB 开始加载的(取决于配置)。我的问题是,最后 1 GB 的映射对于所有进程来说都是相同的,并且映射到内存的这个物理区域?

另一个问题是,当进程切换到内核模式时(例如,当发生sys调用时),那么使用什么页表,进程页表还是内核页表?如果使用内核页表,则它们无法访问属于进程的内存位置。如果是这种情况,那么内核虚拟内存显然没有用处,因为对内核代码和数据的所有访问都将通过最后 1 GB 进程地址空间的映射。请帮我澄清这一点(任何有用的链接将不胜感激)

最佳答案

看来您正在谈论 32 位 x86 系统,对吗?

如果我没记错的话,内核不仅可以配置为 3Gb/1Gb 内存分配,还可能有其他变体(例如 2Gb/2Gb)。尽管如此,3Gb/1Gb 可能是 x86-32 上最常见的一种。

地址空间的内核部分应该无法从用户空间访问。从内核的角度来看,是的,内核本身占用的内存的映射总是相同的。无论如何,内核当前在哪个进程(或中断处理程序,或其他任何东西)的上下文中运行。

结果之一是,如果您从不同的进程查看 /proc/kallsyms 中的内核符号的地址,您每次都会看到相同的地址。从内核的角度来看,这些正是各个内核函数、变量等的地址。

所以我想,你的第一个问题的答案是"is",但它对于用户空间代码可能不是很有用,因为内核空间内存无论如何都不能直接访问。

对于第二个问题,如果内核当前在某个进程的上下文中运行,它实际上可以访问该进程的用户空间内存。我无法详细描述它,但内核函数 copy_from_usercopy_to_user 的实现可能会给您一些提示。请参阅内核源代码中的 arch/x86/lib/usercopy_32.carch/x86/include/asm/uaccess.h。看起来,在 x86-32 上,用户空间内存是在这些函数中直接访问的,使用当前进程上下文的默认内存映射。那里的“神奇”东西只与优化和检查内存区域地址的正确性有关。

关于linux-kernel - Linux 进程地址空间中的最后 GB 是否映射到相同的物理内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6082385/

相关文章:

c - 为什么我们可以分配一个 1 PB (10^15) 的数组并访问最后一个元素,但不能释放它?

c - 关于 Spectre 示例,虚拟/物理地址如何工作?

c++ - 了解 VirtualAlloc 中的基地址

c - 使用管理程序,如何监视目标进程创建或终止的时间

c - 将文件映射到内存并写入文件末尾

linux - 谁在按下ctrl + c,tty驱动程序或shell时将SIGINT发送到前台进程

c - malloc分配的内存在物理上不一定是连续的吗?

c - 在 VMX 中启用 EPT 会因访客状态而导致登录失败

node.js - ReadStream 跳过字节?

c - 为什么我们需要在操作系统中进行地址虚拟化?