Linux 3/1拆分和实物图

nor*_*ake 3 linux memory linux-kernel

我试图了解 Linux 3/1 拆分(或 2/2、1/3、任何)以及映射到物理内存的工作方式。让我们假设 x86。

我特别不明白的是为什么内核在 va[3GiB, 4GiB) 中的 1GiB 总是映射到 pa[0, 1GiB]。拆分位于 (virtual) PAGE_OFFSET

如果我有更多的内存怎么办?如果我少了怎么办?用户空间的所有内存都去哪儿了?

从 TLDP 我了解到,底层物理 1GiB 始终用于内核(为什么?)。当虚拟地址空间小于物理地址空间时,使用高端内存(通过这篇文章),因为内存很多,否则会被浪费(对吧?);在 x86-64 中它没有被使用,因为虚拟地址空间是异常的。

始终保持内核的一件事可能是在上下文切换上current保持不变并且无需更改cr3.

这个答案说:

高端内存是用户空间程序可以寻址的内存段。它不能触及低内存。

Low Memory 是 Linux 内核可以直接寻址的内存段。如果内核必须访问高端内存,它必须首先将其映射到自己的地址空间。

人们是否过度使用“低记忆力”和“高记忆力”这两个术语?

最后,LDD3 说:

内核不能直接操作未映射到内核地址空间的内存。换句话说,内核需要它自己的虚拟地址来处理它必须直接接触的任何内存。因此,多年来,内核可以处理的最大物理内存量是可以映射到内核虚拟地址空间部分的量,减去内核代码本身所需的空间。因此,基于 x86 的 Linux 系统最多可以使用略低于 1 GB 的物理内存。

这是指p内核中的指针必须持有虚拟地址,而不是物理地址,因为映射总是适用的?为什么这个“1GiB 物理内存”限制?

Joh*_*éen 5

32 位 x86 在今天几乎和 16 位 8086 在 1990 年代初 Linux 诞生时一样过时。当时 386 提供的 4 GB 虚拟地址空间已经足够了,因为典型的台式机只有几十兆字节的 RAM。

Linus 决定拆分虚拟地址空间,以便为内核保留高 1 GB(从地址 0xc0000000 开始),而低 3 GB(从地址 0 开始)可供用户空间进程使用。然后从 PAGE_OFFSET 开始映射所有物理 RAM,即从 3 GB 开始的地址。当时 1 GB 已经足够了,因为(正如我之前提到的)物理 RAM 的典型数量比这小得多,并且这种拆分为用户空间留下了舒适的 3 GB 空间。

在打开分页(即虚拟到物理地址映射)之前,包含内核代码和静态数据的内核映像被加载到物理内存的开头。(嗯,不完全是,但通常从 2 MB 开始,因为 PC 平台的一些怪癖。)打开分页时,物理地址 N 处的内存最终位于虚拟地址 N + PAGE_OFFSET。这意味着内核映像占据内核内存区域的较低部分,通常只有几兆字节。

请注意,到目前为止我已经讨论了虚拟地址空间,即为某些事物保留的空间。要实际使用这些地址,您必须将物理 RAM 页框映射到虚拟地址。早期只映射了内核虚拟地址空间的一小部分,因为要映射的物理 RAM 太少了,但是当可以负担得起更大的 RAM 大小时,这种情况很快发生了巨大变化,导致 1 GB 空间不足以映射寻址所有 RAM。因此引入了“高内存”机制,它提供了一个窗口,可以根据需要映射部分额外 RAM。

那么为什么内核需要在其虚拟地址空间中有 RAM。问题是 CPU 只能(以编程方式)通过虚拟(映射)地址访问内存。寄存器中的指针是指向虚拟地址空间的指针,指导程序流的指令指针也是如此。内核需要能够自由访问 RAM,例如将稍后提供给用户空间进程的缓冲区归零。

内核将整个 RAM 囤积到其地址空间并不意味着用户空间无法访问它。可以存在多个到 RAM 页框的映射;当进程被选择执行时,它既可以永久映射到内核内存空间,也可以映射到某个地址到用户空间。