高端内存(High Memory)是 32 位 CPU 架构下的产物,是"虚拟地址空间不足"导致的妥协。而在 AArch64(64 位)架构下,虚拟地址空间巨大,不再存在这个问题,因此不需要高端内存。
下面详细展开讲解。
一、 什么是"高端内存"?为什么会有它?
要理解高端内存,必须回到 32 位 Linux 系统 的背景下。
1. 32 位系统的地址空间限制
在 32 位系统中,CPU 的寻址范围是 232=4GB2^{32} = 4GB232=4GB。Linux 内核通常将这 4GB 的虚拟地址空间 按照 3:1 的比例进行划分:
- 0 ~ 3GB (User Space):给用户态进程使用。
- 3GB ~ 4GB (Kernel Space) :给内核态使用,只有 1GB 的大小。
2. 问题的产生:物理内存 > 内核虚拟空间
内核为了管理物理内存,需要将物理内存映射到自己的虚拟地址空间中。
- 理想情况 :内核采用线性映射 (直接偏移),即
虚拟地址 = 物理地址 + 偏移量。这样访问效率最高。 - 现实困境 :内核的虚拟地址空间只有 1GB 。
- 如果物理内存只有 512MB,内核可以把这 512MB 全部映射到那 1GB 的空间里,绰绰有余。
- 但是,如果物理内存有 2GB、4GB 甚至更多呢? 内核那区区 1GB 的虚拟窗口,根本无法一次性"看全"所有的物理内存。
3. 解决方案:高端内存 (HighMem)
为了解决这个问题,Linux 内核将那 1GB 的内核虚拟空间分成了两部分:
-
低端内存 (Low Memory / ZONE_NORMAL):
- 大约前 896MB 的物理内存。
- 这部分内存被永久、线性地映射到内核虚拟空间。内核可以直接通过指针访问,效率极高。
- 用于存放内核代码、页表、关键数据结构(如
task_struct)。
-
高端内存 (High Memory / ZONE_HIGHMEM):
- 物理内存中超过 896MB 的部分。
- 内核不能直接访问这部分内存,因为没有固定的虚拟地址映射。
- 访问方式 :当内核需要读写这部分物理内存时,必须使用
kmap()等函数,在内核虚拟空间的最后 128MB(专门留出的动态映射区)中临时借用 一个虚拟地址,建立映射,用完后再用kunmap()解除映射。
比喻 :
这就好比你只有一扇很小的窗户(1GB 的内核空间),而外面的风景(物理内存)很大。
- 窗户正对着的风景(低端内存),你随时都能看到。
- 窗户两边的风景(高端内存),你必须探出头去,或者用镜子折射(动态映射)才能看到,看完还得把头缩回来,非常麻烦且慢。
二、 为什么 AArch64 (ARM64) 上没有高端内存?
到了 64 位时代(x86_64 或 AArch64),情况发生了根本性的变化。
1. 巨大的虚拟地址空间
在 64 位架构下,理论寻址范围是 2642^{64}264。虽然实际硬件通常只实现了 48 位或 52 位,但这依然是一个天文数字:
- 48 位地址空间 = 256 TB。
- Linux 内核通常将这巨大的空间对半切分,内核空间拥有 128 TB 的虚拟地址范围。
2. 物理内存 < 内核虚拟空间
现在的服务器或手机,物理内存通常是 8GB、16GB,哪怕是顶配服务器也就几 TB。
128 TB 的内核虚拟地址空间 >>> 实际的物理内存大小。
3. 结果:全员"低端内存"
因为内核的虚拟地址空间太大了,大到可以把所有的物理内存(哪怕你有 100TB)都一次性、永久地进行线性映射(Direct Mapping)。
- 内核不再需要"临时借用窗口"这种蹩脚的操作。
- 所有的物理内存都可以通过简单的线性偏移直接访问。
- 因此,
ZONE_HIGHMEM这个内存管理区在 64 位内核配置中默认是关闭的,或者根本不存在。
比喻 :
在 64 位系统里,你的"窗户"变成了一整面巨大的落地玻璃墙(128TB)。无论外面的风景(物理内存)有多大,你都能一眼看全,根本不需要探头探脑。
三、 总结对比
| 特性 | 32 位 (ARM32/x86) | 64 位 (AArch64/x86_64) |
|---|---|---|
| 内核虚拟空间 | 只有 1GB (通常) | 128 TB 或更大 |
| 物理内存瓶颈 | 物理内存很容易超过 1GB | 物理内存远小于虚拟空间 |
| 映射方式 | LowMem : 线性映射 HighMem: 动态映射 (kmap) | 全部物理内存均为线性映射 (Phys-to-Virt) |
| 性能影响 | 访问高端内存需要建立/解除页表映射,慢 | 直接访问,快 |
| 是否存在 HighMem | 存在 (ZONE_HIGHMEM) | 不存在 (所有内存都是 ZONE_NORMAL) |
补充:AArch64 上的内存区域 (Zones)
虽然没有了 ZONE_HIGHMEM,但 AArch64 Linux 内核中通常还有以下 Zone:
- ZONE_DMA / ZONE_DMA32:用于旧式硬件 DMA 寻址限制(例如只能访问低 4GB 物理内存的设备)。
- ZONE_NORMAL:覆盖了剩余的所有物理内存。
所以在 AArch64 上,你所有的内存条,在内核眼里都是 ZONE_NORMAL,都可以直接访问。