在Linux系统中,”highmem”(高端内存)机制主要解决32位架构下物理内存寻址限制的问题,32位系统的虚拟地址空间通常被划分为用户空间(3GB)和内核空间(1GB),导致内核无法直接访问超过约896MB的物理内存,Highmem通过动态映射扩展了内核的内存管理能力,以下是其启动过程的详细解析:
- 地址空间划分:
- 低端内存(Lowmem):内核直接映射的物理内存(默认0~896MB),永久映射到内核空间,访问无额外开销。
- 高端内存(Highmem):超出896MB的物理内存,需通过动态临时映射供内核使用。
- 映射机制:
kmap()
:为Highmem页创建临时内核映射,适用于长时操作。kmap_atomic()
:基于CPU的”临时映射槽”(每个CPU有固定槽位),适用于短时、不可中断的操作(如中断处理)。
Highmem的启动流程
阶段1:内核初始化(start_kernel)
- 内存检测:
内核通过BIOS/UEFI获取物理内存布局(e820
/efi
映射表),识别总内存大小,若超过lowmem_limit
(通常896MB),则启用Highmem支持。 - 关键函数调用链:
start_kernel()
→setup_arch()
→init_mem_mapping()
→paging_init()
- 在
paging_init()
中建立低端内存的固定映射(__va
直接转换)。 - 若检测到>896MB内存,初始化Highmem区(
highmem_start_pfn
~max_pfn
)。
- 在
阶段2:Highmem映射框架构建
- 临时映射区(FIXADDR)初始化:
- 在
fixed_address_init()
中预留FIX_KMAP
区域(通常位于内核空间顶部)。 - 为每个CPU分配一组
kmap_atomic
槽位(默认每个CPU 512个槽)。
- 在
- 永久映射区(PKMAP)初始化:
- 在
pkmap_page_table
中分配512KB空间(PAGE_OFFSET
上方),用于kmap()
的持久映射。 - 建立页表项,初始状态标记为”未使用”。
- 在
阶段3:内存管理子系统激活
mem_init()
函数:- 计算
highmem
页框数量:totalhigh_pages = max_pfn - lowmem_pages
。 - 将Highmem页加入伙伴分配器(Buddy Allocator),标记为
ZONE_HIGHMEM
。 - 输出日志:
"High memory: X MB"
(如High memory: 1024 MB
)。
- 计算
Highmem的运行时操作
- 分配Highmem页:
- 通过
alloc_page(GFP_HIGHUSER)
从ZONE_HIGHMEM
分配物理页。
- 通过
- 映射到内核空间:
kmap()
流程:- 若页面在Lowmem,直接返回
__va(page_phys)
。 - 若在Highmem,从PKMAP区分配槽位,建立映射并返回虚拟地址。
- 若页面在Lowmem,直接返回
kmap_atomic()
流程:- 根据CPU ID和类型(如
KM_USER0
)选择槽位。 - 更新页表项,禁用抢占(操作期间不允许调度)。
- 根据CPU ID和类型(如
配置与优化
- 内核编译选项:
CONFIG_HIGHMEM=y
:启用Highmem支持(32位内核默认开启)。CONFIG_HIGHMEM4G
:针对4GB内存优化。CONFIG_HIGHMEM64G
:支持最大64GB内存(需PAE扩展)。
- 启动参数调整:
highmem=size
:手动指定Highmem大小(如highmem=2G
)。vmalloc=size
:扩大vmalloc区(可能影响Highmem映射空间)。
常见问题与解决方案
-
内核崩溃:
Unable to handle kernel paging request
原因:Highmem页未正确映射时被访问。
解决:检查kmap/kmap_atomic
调用是否成对,确保映射在有效上下文(如非中断上下文使用kmap
)。 -
性能下降
原因:频繁的Highmem映射/解映射导致TLB刷新。
优化:- 减少
kmap
调用次数(缓存映射结果)。 - 使用
kmap_atomic
替代kmap
(避免全局锁竞争)。
- 减少
-
64位系统无需Highmem
64位架构(如x86_64)的内核空间为128TB,可直接映射所有物理内存(CONFIG_HIGHMEM=n
)。
Highmem是32位Linux系统的关键扩展机制,通过动态映射突破内核寻址限制,其启动过程分为内存检测、映射区初始化和页框管理三步,核心依赖kmap
/kmap_atomic
实现按需映射,随着64位系统的普及,Highmem的重要性已降低,但在嵌入式或旧硬件场景中仍需深入理解其原理。
引用说明:
- Linux内核源码(v5.10):
arch/x86/mm/init_32.c
,mm/highmem.c
- 《Understanding the Linux Kernel, 3rd Edition》(O’Reilly)
- Kernel Documentation: High Memory Handling
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/6920.html