在32位Linux系统中,内核空间的线性映射(也称为直接映射或低端内存映射)采用固定的偏移量进行虚拟地址和物理地址的换算。以下是详细的转换规则及背景知识:
1. 32位Linux内存布局
用户空间:虚拟地址 0x00000000 到 0xBFFFFFFF(0~3GB),供用户态进程使用。
内核空间:虚拟地址 0xC0000000 到 0xFFFFFFFF(3GB~4GB),保留给内核使用。其中,内核空间的起始地址 PAGE_OFFSET 默认为 0xC0000000(3GB)。
2. 线性映射规则
内核通过固定偏移量将物理内存直接映射到虚拟地址空间,使得大部分物理内存可以通过简单的算术运算转换为虚拟地址,无需复杂页表查询。
虚拟地址到物理地址:
物理地址=虚拟地址−PAGE_OFFSET
物理地址到虚拟地址:
虚拟地址=物理地址+PAGE_OFFSET
示例:
物理地址 0x1000 ➔ 虚拟地址 0xC0001000。
虚拟地址 0xC0005000 ➔ 物理地址 0x5000。
3. 适用条件
低端内存(Low Memory):物理地址范围 0x00000000 到 HIGH_MEMORY(通常为896MB)。这部分内存通过线性映射直接访问。
高端内存(High Memory):物理地址超过896MB时,内核无法全部线性映射,需通过动态机制(如kmap或vmalloc)访问。虚拟地址范围为 0xFIXADDR_START ~ VMALLOC_END(如 0xFF000000)。
4. 内核实现细节
相关宏:
#define __pa(vaddr) ((unsigned long)(vaddr) - PAGE_OFFSET) // 虚拟地址转物理地址
#define __va(paddr) ((void *)((unsigned long)(paddr) + PAGE_OFFSET)) // 物理地址转虚拟地址
页表设置:内核启动时通过恒等映射(偏移量 PAGE_OFFSET)建立页表项,确保虚拟地址 0xC0000000 对应物理地址 0x00000000。
5. 例外情况
设备内存映射:某些硬件设备的物理地址可能位于非低端内存区域,需通过ioremap映射到内核空间。
CONFIG_HIGHMEM:启用该配置后,内核可管理超过线性映射范围的物理内存,但需通过临时映射访问。
6.与 ARM64 的对比
总结
在32位Linux中,内核空间的线性映射通过固定偏移 PAGE_OFFSET(0xC0000000)实现虚拟地址与物理地址的转换,适用于低端内存。这种机制简化了内核访问物理内存的流程,但受限于32位地址空间,需结合高端内存机制管理大容量物理内存。