我读到前3 GB是为进程保留的,最后一个GB是为内核保留的。我还读到内核是从物理地址空间的第2 MB开始加载的(取决于配置)。我的问题是,最后1 GB的映射是否适用于所有进程并映射到此物理内存区域?
另一个问题是,当进程切换到内核模式时(例如,发生sys调用时),那么使用了哪些页表,进程页表还是内核页表?如果使用内核页表,则它们无法访问属于该进程的内存位置。如果是这种情况,那么内核虚拟内存显然没有用,因为对内核代码和数据的所有访问都将通过最后1 GB进程地址空间的映射。请帮助我澄清一下(非常感谢任何有用的链接)
答案 0 :(得分:4)
看来,你在谈论32位x86系统,对吧?
如果我没有弄错的话,内核不仅可以配置为3Gb / 1Gb内存分配,还可以有其他变种(例如2Gb / 2Gb)。不过,3Gb / 1Gb可能是x86-32上最常见的一个。
地址空间的内核部分应该无法从用户空间访问。从内核的角度来看,是的,内核本身占用的内存映射总是一样的。无论如何,在内核当前运行的进程(或中断处理程序或其他任何内容)的上下文中。
作为其中一个后果,如果您查看来自不同进程的/proc/kallsyms
中的内核符号的地址,您每次都会看到相同的地址。从内核的角度来看,这些正是各个内核函数,变量和其他内容的地址。
所以我想,你的第一个问题的答案是肯定的,但它对用户空间代码可能不是很有用,因为无论如何都无法从那里直接访问内核空间内存。
至于第二个问题,如果内核当前在某个进程的上下文中运行,它实际上可以访问该进程的用户空间内存。我无法详细描述它,但可能内核函数copy_from_user
和copy_to_user
的实现可能会给你一些提示。请参阅内核源代码中的arch/x86/lib/usercopy_32.c
和arch/x86/include/asm/uaccess.h
。看来,在x86-32上,使用当前进程上下文的默认内存映射直接在这些函数中访问用户空间内存。那里的“神奇”东西只与优化有关,并且检查内存区域的地址是否正确。
答案 1 :(得分:2)
是的,地址空间的内核部分的映射在所有进程中都是相同的。 它的部分确实映射了加载内核映像的物理内存部分,但这不是其中的大部分 - 剩余部分用于映射内核运行时工作集的其他物理内存位置。
当进程切换到内核模式时,页表不会更改。地址空间的内核部分只是变得可访问,因为CPL(当前特权级别)现在为零。