我发现了类似的问题,但仍然没有回答我的问题 所有进程的虚拟地址空间在其“内核”部分是否具有相同的内容?
首先,考虑到用户进程无权访问这部分,我想如果他们尝试访问它,就会导致错误,那么为什么还要将这部分包含在用户进程虚拟空间中呢?你们能给我一个现实生活中的场景,说明这部分是重要且有用的吗?
另外,还有一个问题是我一直认为内存的内核部分是动态的,这意味着它可能会增长,例如当我们在程序中使用动态库时,这是真的吗?如果是这样,那么操作系统如何确定进程虚拟空间中内核的大小有多大?
当物理内存中的内核增长或更改时,所有进程的虚拟内存的内核部分是否会发生相同的效果?这个虚拟内核到真实内核的映射是一对一的映射吗?
答案1
内核映射主要是为了内核的目的而存在,而不是为了用户进程的目的。从 CPU 的角度来看,任何未映射为线性地址的物理内存地址可能都不存在。但是CPU确实需要能够调用内核:服务中断、处理异常......它还需要能够在用户进程发出系统调用时调用内核(有多种方法可以实现)发生了所以我不会详细说明)。在大多数(如果不是全部)架构上,这种情况发生时没有机会切换页表 - 例如参见
SYSENTER
。因此,至少,内核的入口点必须始终映射到当前地址空间。核心分配是动态的,但地址空间不是。在 32 位 x86 上,可以使用各种拆分,例如图中所示的 3/1 GiB 拆分;在 64 位 x86 上,地址空间的上半部分是为内核保留的(请参阅内存映射在内核文档中)。那裂痕无法移动。 (请注意,库被加载到用户空间。内核模块被加载到内核空间,但同样,这仅更改分配,而不更改地址空间分割。)
在用户模式下,内核有一个映射,在所有进程之间共享。当内核端页面映射发生更改时,该更改会反映到各处。
当启用 KPTI 时,内核有自己的私有映射,在运行用户空间代码时不会公开这些映射;因此,KPTI 有两种映射,并且对内核私有映射的更改对用户空间不可见(这就是 KPTI 的全部意义)。
内核内存映射始终映射所有内核(运行 KPTI 时在内核模式下),但它不一定是一对一的 — 例如在 64 位 x86 上,它包含物理内存的完整映射,因此所有内核物理地址都是至少映射两次。
答案2
另一个小技巧是根据内核的定义进行更普遍的理解,它应该始终处于活动状态以执行管理服务并向用户应用程序提供服务。这种活跃性实际上是通过在每个进程中逻辑绑定内核来实现的。
这也是有道理的,考虑到多个进程在单处理器机器环境中运行,并且还要考虑进程结构不包含内核映射。由于只有一个处理器,一旦一个进程被调度运行,就肯定意味着内核不活跃,因为CPU被该进程占用,而且我们假设该进程中没有可用的内核映射。现在逻辑问题是内核将如何执行其服务,解决方案是将内核映射到每个进程中。
这就是我认为每个人都与造物主有映射的方式。