#Linux内存管理# 在ARM32bit Linux中,高端内存的起始地址是如计算出来的?

在32位Linux系统中,高端内存(High Memory)的起始地址是由内核虚拟地址空间和物理内存容量共同决定的。以下是其计算逻辑和关键步骤:

1. 32位虚拟地址空间划分

32位系统的虚拟地址空间为 4GB(0x00000000 ~ 0xFFFFFFFF),通常划分为:

 

用户空间:前 3GB(0x00000000 ~ 0xBFFFFFFF),供应用程序使用。

 

内核空间:后 1GB(0xC0000000 ~ 0xFFFFFFFF),供内核使用。

 

内核需要通过这 1GB 的虚拟地址空间 访问所有物理内存。当物理内存超过 1GB 时,内核无法直接为所有物理页分配固定的虚拟地址,此时需要引入 高端内存 机制。

 

2. 低端内存(Low Memory)与高端内存(High Memory)

 

低端内存:

内核通过 直接映射(Direct Mapping) 将一部分物理内存固定映射到内核虚拟地址空间。

虚拟地址范围:0xC0000000 ~ (0xC0000000 + lowmem_size)。

物理地址范围:0x00000000 ~ lowmem_size(直接线性映射)。

最大低端内存:通常为 896MB(由内核参数 lowmem_end_pfn 决定)。

 

高端内存:

超出低端内存的物理内存部分(即 lowmem_size ~ 物理内存上限)无法直接映射到内核虚拟地址空间,必须通过动态映射(如 kmap、vmalloc)访问。

 

3. 高端内存起始地址的计算

 

高端内存的起始地址是物理内存中超出低端内存部分的第一个物理地址,计算公式如下:

high_memory_start=lowmem_size

 

其中,lowmem_size 的计算逻辑为:

lowmem_size=lowmem_end_pfn×PAGE_SIZE

 

lowmem_end_pfn:由内核根据物理内存容量和地址空间限制动态确定。

 

PAGE_SIZE:通常为 4KB。

 

4. 内核源码中的实现

 

在 Linux 内核中,相关定义位于 arch/x86/include/asm/pgtable_32_types.h:

#define __PAGE_OFFSET _AC(0xC0000000, UL) // 内核空间起始地址

#define MAXMEM _AC(896MB, UL) // 低端内存最大为 896MB

#define high_memory (void *)((0xC0000000UL) + (MAXMEM)) 

 

MAXMEM:低端内存的虚拟地址上限(0xC0000000 + 896MB = 0xF0000000)。

 

high_memory:高端内存的起始虚拟地址(实际对应物理地址 896MB)。

 

5. 案例分析:物理内存为 2GB 的系统

 

低端内存:直接映射 896MB(虚拟地址 0xC0000000 ~ 0xF0000000)。

 

高端内存:物理地址从 896MB 到 2GB 的部分(共 1152MB)。

 

访问高端内存:

内核需通过 kmap() 将高端内存的物理页临时映射到内核虚拟地址空间。

映射的虚拟地址位于 0xF0000000 ~ 0xFFFFFFFF(即剩余的 256MB 内核空间)。

 

6. 关键验证方法

查看 /proc/meminfo 或内核日志:

$ dmesg | grep "Memory"

[ 0.000000] Memory: 2048MB/2048MB (lowmem: 896MB, highmem: 1152MB)

 

总结

低端内存:内核直接映射的物理内存(≤896MB),虚拟地址与物理地址线性对应。

 

高端内存:超出低端内存的物理内存部分,必须通过动态映射访问。

 

起始地址:高端内存的物理起始地址为 lowmem_size(通常为896MB),由内核虚拟地址空间大小和物理内存容量共同决定。

 

你可能感兴趣的:(linux)