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