在 Linux 进程的虚拟内存空间中拥有内核部分有什么用?

Joh*_*n P 18 linux process kernel memory linux-kernel

我发现了一个类似的问题,但它仍然没有回答我的问题 所有进程的虚拟地址空间在它们的“内核”部分都有相同的内容吗?

  1. 首先,考虑到用户进程无权访问这部分,我猜如果他们尝试访问它,会导致错误,那么为什么还要将这部分包含在用户进程虚拟空间中呢?你们能给我一个真实的生活场景,说明这部分必不可少和有用吗?

  2. 另外,还有一个问题是我一直认为内存的内核部分是动态的,这意味着它可能会增长,例如当我们在我们的程序中使用动态库时,这是真的吗?如果是这样,那么操作系统如何确定我们进程的虚拟空间中内核的大小?

  3. 当我们在物理内存中的内核增长或变化时,是否会在所有进程的虚拟内存的内核部分发生相同的效果?这个虚拟内核到真实内核的映射是一对一的映射吗?

在此处输入图片说明

Ste*_*itt 15

  1. 内核映射主要用于内核的目的,而不是用户进程的目的。从 CPU 的角度来看,任何未映射为线性地址的物理内存地址也可能不存在。但是 CPU 确实需要能够调用内核:服务中断,处理异常......它也需要能够在用户进程发出系统调用时调用内核(有多种方法可以做到这一点)发生,所以我不会详细介绍)。在大多数(如果不是全部)架构上,这种情况发生时没有机会切换页表——例如参见SYSENTER。因此,至少,内核的入口点必须始终映射到当前地址空间。

  2. 内核分配是动态的,但地址空间不是。在 32 位 x86 上,可以使用各种拆分,例如图中所示的 3/1 GiB 拆分;在 64 位 x86 上,地址空间的上半部分是为内核保留的(请参阅内核文档中的内存映射)。那个裂不能动。(请注意,库被加载到用户空间。内核模块被加载到内核空间,但同样只更改分配,而不是地址空间拆分。)

  3. 在用户模式下,内核只有一个映射,在所有进程之间共享。当内核端页面映射更改时,该更改会反映到任何地方。

    启用 KPTI 后,内核有自己的私有映射,在运行用户空间代码时不会公开;因此,对于 KPTI,有两个映射,并且对内核私有映射的更改对用户空间是不可见的(这是 KPTI 的重点)。

    内核内存映射总是映射所有内核(在运行 KPTI 时在内核模式下),但它不一定是一对一的——例如在 64 位 x86 上它包括物理内存的完整映射,所以所有内核物理地址都是至少映射两次。

  • 在 64 位 x86 上,内核内存映射包括所有物理内存的直接映射,因此内存中的所有内容都会出现在那里;它还包括内核、模块等的单独映射,因此包含内核的物理地址至少出现在两种不同的映射中(直接物理映射和各种内核映射)。 (2认同)
  • 至于为什么要映射整个内核,当KPTI没有启用时,主要是因为这样更简单。内核几乎完全由进程可能需要的操作系统服务组成,要么是因为它们实现了系统调用及其支持的基础设施(文件系统等),要么是因为它们提供了硬件支持(设备驱动程序,包括中断处理程序等)。内核无法提前知道进程将使用什么。 (2认同)