Linux 内核中的内存映射 - 使用 vamlloc() 和 kmalloc()

Memory Mapping in Linux Kernel - use of vamlloc() and kmalloc()

考虑一个 32 位 x86 Linux 系统,具有 4 GB RAM 内存,因此如书中所述以及在许多论坛上,内存映射如下:

  1. 内核逻辑地址 - 高达 896 MB - 这是一对一映射的,可以使用 kmalloc 分配().
  2. 内核虚拟地址-128MB(896MB以上-内核逻辑地址)-使用vmalloc()[分配=41=] 并分配虚拟连续但物理上(分散在 RAM 内)非连续内存页。

有几点我不能完全理解并需要澄清。

  1. 我的理解是,当使用kmalloc()分配内存时,它总是来自RAM中的0到896MB,而不是超出。

  2. 当我们使用 vmalloc() 分配内存时,分配的内存是否在 RAM 中的 896MB 到 4GB 范围内?还是仅在 RAM 中从 896MB 到 1GB 范围分配?

  3. 当我们说内核只有1GB的虚拟地址时space,是否意味着内核不能访问超过1GB的RAM?如果可以那么它是如何完成的? 128MB的内核虚拟地址space是否用于此目的?

请帮忙。

理论上有3种不同"memory managers"。一个管理物理 RAM(主要跟踪空闲物理 RAM 的页面),一个管理虚拟 space(映射到每个虚拟地址 space 的内容,其中使用固定大小的块 - 页面大小),第三个管理 "heap"(允许将更大的虚拟地址 space 分成任意大小的部分)。

最初; Linux 内核试图使用它的内核 "heap" 来管理这三个截然不同的东西。通过将 "all RAM" 线性映射到内核 space,他们绕过了管理内核虚拟内存的需要,并最终在内核 space 中的虚拟地址和物理地址(例如 "physical = virtual - base"), 并且通过分配 "heap" 你也分配了物理内存。

这本来很好,因为当时计算机很少有超过 128 MiB 的 RAM(而且 Linus 没想到内核会存在很长时间,因为 GNU 正计划切换到 Hurd "soon" ),内核 space 明显大于 "all RAM"。随着 RAM 数量的增加,它变成了一个问题 -"all RAM" 变得比内核 space 大,所以 "use heap to manage 3 very different things" 无法工作。

当然,一旦它成为一个问题,很多内核的代码都依赖于 "kmalloc to allocate physical memory",这使得修复这个问题变得太难了。相反,他们将物理内存分成 2 个区域——一个区域由 "kmalloc" 管理,另一个区域由 "vmalloc" 管理;然后将内核的一部分更改为使用 "vmalloc" 而不是 "kmalloc",在这些地方很容易进行这些更改。

  1. My understanding is that When kmalloc() is used to allocate memory, It always comes from the 0 to 896MB within the RAM and not beyond that.

是;这是物理内存的第一个区域,适合 "kmalloc" 使用的内核 space 映射。

  1. When we use vmalloc() to allocate memory, Does that memory allocated anywhere from 896MB to 4GB range within the RAM ? or it is allocated only from 896MB upto 1GB range within RAM?

它将从不在第一个区域(“896MB 或更高”范围内的任何地方)的任何 RAM 中分配。

  1. When we say that kernel has only 1GB of virtual address space, Does that meant that the kernel can not access the RAM beyond 1GB ? If it can then how it is done ? Does the 128MB of kernel virtual address space are used for this purpose ?

内核的 1 GiB 虚拟 space;一些 (896MB) 将是物理地址 space 的线性映射,一些将是内存映射 (PCI) 设备,还有一些将预留为可以进行动态映射的区域。对于 "vmalloc" ,内核将分配 RAM 的物理页面,然后将它们映射到 "dynamic mapping area" (和 return 一个指向其映射位置的指针,与它的物理地址和中断无关"physical = virtual - base" 关系)。

注 1:确切的 sizes/limits 是可变的 - 例如内核可以编译为“2 GiB / 2 GiB 拆分”,其中内核 space 是 2 GiB(而不是“3 GiB / 1 GiB 拆分”); "kmalloc zone" 的大小可能取决于各种因素(space PCI 设备需要多少,有多少 RAM,等等)并且可能不是 896MB。

注 2:由于引入 "vmalloc" 来解决原始问题;计算机切换到 64 位(其中 "all memory" can/does 再次适合内核 space),并且 "vmalloc" 变得不必要(并且可能只是下降到 "kmalloc")。然而,发生了许多其他变化(NUMA、加密 RAM、非易失性 RAM 的引入,..;再加上任何人都无法追踪的更多安全漏洞),所以最初的设计缺陷已经达到了暂时的 "bad idea, but still technically not broken if we keep adding work-arounds for security vulnerabilities" 阶段(直到 RAM 和非易失性 RAM 大小不可避免地增加并且 "vmalloc" 在将来的某个时候再次需要 - 可能在大约 30 年内)。