Linux内核内存管理 ARM64 内核内存布局的详细解析

一、虚拟地址空间划分

ARM64 架构采用 48 位虚拟地址空间(最大支持 52 位,但主流实现为 48 位),划分为两部分:

 

用户空间:0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF(256TB),供用户进程使用。

 

内核空间:0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF(256TB),由内核独占。

 

核心特点:

无高端内存:48 位寻址空间足够大(256TB),无需像 ARM32 那样动态映射高端内存。 

 

统一线性映射:物理内存通过固定偏移量直接映射到内核空间,简化访问流程。

 

二、内核空间详细布局

 

内核空间按功能划分为以下区域(以 4KB 页大小 + 4 级页表配置为例):

1. 线性映射区(Normal Memory)

范围:0xFFFF_8000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF(128TB)。

 

作用:直接映射全部物理内存,虚拟地址与物理地址呈线性关系:

虚拟地址 = 物理地址 + PAGE_OFFSET(PAGE_OFFSET 通常为 0xFFFF_8000_0000_0000)。

 

特点:

用于内核代码段(.text)、数据段(.data)、堆等核心内存。

通过 kmalloc() 或 __get_free_page() 分配的内存来自此区域。

支持大页(2MB 或 1GB)映射,减少页表层级和 TLB 未命中率。

2. vmalloc 动态映射区

范围:0xFFFF_0000_0000_0000 ~ 0xFFFF_7BFF_BFFF_0000(约 126,974GB)。

 

作用:分配虚拟连续但物理离散的内存(如 DMA 缓冲区、动态模块加载)。 

 

特点:

物理页通过 vmalloc() 动态分配,性能低于线性映射区。

典型用例:大块非连续内存需求或物理内存碎片化场景。

3. vmemmap 区

范围:0xFFFF_7BFF_C000_0000 ~ 0xFFFF_7FFF_C000_0000(4,096GB)。

 

作用:存储物理页的 struct page 元数据数组。

 

特点:

每个 struct page 描述一个物理页,总大小与物理内存容量相关。

默认使用稀疏内存模型(SPARSEMEM)优化内存占用。

4. PCI I/O 区

范围:0xFFFF_7FFF_AE00_0000 ~ 0xFFFF_7FFF_BE00_0000(16MB)。

 

作用:映射 PCI 设备的 I/O 内存空间。

 

特点:

通过 ioremap() 动态映射外设寄存器。

访问需遵循设备特定的内存序和缓存策略。

5. 模块加载区(Modules)

范围:0xFFFF_7FFF_C000_0000 ~ 0xFFFF_8000_0000_0000(64MB)。

 

作用:加载内核模块(.ko 文件)的代码和数据。

6. 固定映射区(Fixmap)

范围:0xFFFF_FFFE_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF(约 2GB)。

 

作用:预留给固定用途的虚拟地址(如早期启动阶段的临时页表映射)。

 

特点:

虚拟地址固定,物理地址在运行时动态绑定。

常用于 MMU 启用前的内存初始化。

 

三、典型内存布局示例

 

以 QEMU 实验平台为例,ARM64 内核内存布局如下(通过 dmesg 或 /proc/iomem 查看):

 

用户空间:0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF (256TB) 

 

内核空间: vmalloc : 0xFFFF_0000_0000_0000 ~ 0xFFFF_7BFF_BFFF_0000 (126,974GB) vmemmap : 0xFFFF_7BFF_C000_0000 ~ 0xFFFF_7FFF_C000_0000 (4,096GB) PCI I/O : 0xFFFF_7FFF_AE00_0000 ~ 0xFFFF_7FFF_BE00_0000 (16MB) Modules : 0xFFFF_7FFF_C000_0000 ~ 0xFFFF_8000_0000_0000 (64MB) 线性映射区 : 0xFFFF_8000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF (128TB)

 

四、关键机制与优化

 

线性映射优势:

直接通过偏移量访问物理内存,减少地址转换开销。

支持大页映射(如 2MB/1GB),降低页表层级和 TLB 未命中率。

 

连续映射标志(PTE_CONT):

若虚拟地址、物理地址及长度按 64KB 对齐,合并多个 PTE 项以减少 TLB 压力。

 

启动阶段内存初始化:

paging_init():初始化内核页表,建立线性映射和固定映射。

mem_init():移交内存管理权给 Buddy 分配器,释放早期启动内存。

 

五、与 ARM32 的对比

 

 

六、实际应用场景

 

驱动开发:外设寄存器通过 ioremap() 映射到 PCI I/O 区,需注意内存序和缓存策略。

 

性能调优:优先使用线性映射区分配内存(如 kmalloc()),减少 vmalloc 调用。 

 

内存调试:通过 /proc/vmallocinfo 或 vmalloc 区日志分析动态内存分配。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux技术芯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值