上面介绍的是我只有 512 MB 物理内存的情况。到目前为止,我读到的是 ZONE_NORMAL 映射到内核虚拟地址空间,如图所示。本质上我有 512 MB 物理内存,其中 496 MB 的 ZONE_NORMAL 映射到内核虚拟空间。基于这种理解,我的问题如下:
- ZONE_NORMAL 是否包含仅有的内核空间页面 ?
- 如果 ZONE_NORMAL 仅由内核页面组成并被映射完全地到内核空间虚拟地址范围,用户空间页面位于哪里?物理内存中似乎没有任何空间用于用户空间页面。
我完全混淆了物理内存小于 4GB 的情况,如我提出的这种情况所示。
如果有人能阐明这一点,我将非常感激。
答案1
在 32 位架构上,您有0xffffffff
(4'294'967'295
或 4 GB)线性地址(不是物理空间)来引用物理地址。
即使只有 512 MB 的物理存储(连接到总线的真实 RAM 棒),内核仍将使用4'294'967'295
(4 GB) 线性地址来计算物理地址。
Linux 内核将这 4 GB(地址)按 3/1 划分为用户空间(高位内存)和内核空间(低位内存),因此内核空间有1'073'741'823
(1 GB)线性地址可供使用。
这 1 GB 的线性地址只能由内核访问,并且会被进一步划分。
区域_DMA:包含小于 16 MB 的内存页框。这用于旧的 ISA 总线,它们只能寻址 RAM 的前 16 MB。
区域_正常:包含 16 MB 及以上且 896 MB 以下的内存页帧,这些是内核可以直接映射/访问的地址。
ZONE_HIGHMEM:包含 896 MB 及以上的内存页框,此边界以上的页框通常不会映射到内核空间,因此内核无法直接访问。来自用户空间的页面框架可以临时或永久映射到此处。
不同区域占用多少实际物理 RAM 空间取决于您运行的进程的形式和数量。
如果您free -ml
在控制台中输入,您可以看到使用情况,包括低内存和高内存:
total used free shared buffers cached
Mem: 3022 2116 905 0 105 1342
Low: 839 196 642
High: 2182 1919 263
-/+ buffers/cache: 667 2354
Swap: 2859 93 2766
答案2
同一物理页可以映射到多个虚拟地址。
ZONE_NORMAL 由可以映射的页面组成经过内核。大多数内存不属于内核,但内核需要在某个时刻映射所有内存(不一定同时映射所有内存)。例如,当内核正在处理write
系统调用时,它需要从用户提供的缓冲区复制数据,这意味着缓冲区必须映射到内核的虚拟地址空间中。
该图描述了没有高内存的(相对)简单情况。 (如果您使用高端 ARM 设备,现在是开始学习高内存的时候了。)然后内核可以同时映射所有进程内存和所有物理内存。
这是内核代码所看到的虚拟内存重新分区的示例(我不确定确切的数字是否可能,但基本思想应该是正确的)。也就是说,我正在描述内核代码使用的指针的含义。
0x00000000..0x00000fff
: 未分配。在此范围内的指针无效。0x00001000..0xbfffffff
:进程内存。这是一个指向进程虚拟地址空间的指针,正在考虑的内核代码正在处理系统调用。该范围内的页面可能未分配,或者可以分配并换入(在这种情况下它也有物理地址),或者可以分配并换出(在这种情况下它没有物理地址) RAM,但它在交换中有一个位置)。0xc0000000..0xdfffffff
: 物理内存。此范围内的指针表示物理地址 p-0xc0000000。该指针的解释实际上并不依赖于MMU。0xe0000000..0xffefffff
: 未分配。在此范围内的指针无效。0xff000000..0xffffffff
: 内核内存。这是指向内核代码或数据的指针。此范围内的页面具有由 MMU 找到的关联物理地址。
我发现Linux 设备驱动程序很好地介绍了 Linux 内核的内部结构。最终,您可能想要转向来源。