4.5 初级内存管理单元
1. 获得物理内存信息
//每条物理地址空间信息占用 20B
struct E820
{
unsigned long address; // 起始地址
unsigned long length; // 长度(单位是字节)
unsigned int type; // 内存类型值: 01H 可用的物理内存
}__attribute__((packed));
可用内存Type=0x0000 0001(9f000h + 7fef0000h)B = 7ff8f000h B ≈ 2047.55 MB 约2 GB
物理页大小为2MB,可用的物理页个数应该为 2047.55 MB / 2 ≈ 1023.775,但是程序运行打印的结果却是1022,为什么?我们看下OS Can Used Total 2M PAGEs的计算方式:
for(i = 0;i <= memory_management_struct.e820_length;i++)
{
unsigned long tmp_start,start,tmp_end,end,mem;
if(memory_management_struct.e820[i].type != 1)
continue;
// 按2M对齐
tmp_start = memory_management_struct.e820[i].address;
start = PAGE_2M_ALIGN(tmp_start);
tmp_end = (memory_management_struct.e820[i].address + memory_management_struct.e820[i].length);
color_printk(RED,BLACK,"memory_management_struct.e820[%d]--tmp_start::%#016x--start::%#016x--tmp_end::%#016x\n",i,tmp_start,start,tmp_end);
end = (tmp_end >> PAGE_2M_SHIFT) << PAGE_2M_SHIFT;
if(end <= start)
continue;
mem = (end - start) >> PAGE_2M_SHIFT;
TotalMem += mem;
color_printk(RED,BLACK,"memory_management_struct.e820[%d]--end::%#016x--mem::%#016x--TotalMem::%#016x\n",i,end,mem,TotalMem);
}
输出结果如下图:
可以看到,采用了“掐头去尾”的方式和2M的内存进行对齐,最终算得可用的物理页个数为 0x3fe = 1022
保存内存信息的结构体
2.初始化 Global_Memory_Descriptor memory_management_struct 结构体实例的成员变量,分配内存并简单初始化
// 此刻的TotalMem是 0x 0000 0000 fffc 0000 + 0x4 0000 = 0x0000 0001 0000 0000 = 0b0000 0000 0000 0000 0000 0000 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 = 4294967296 = 4GB
// 先按所有的内存进行分区,不再考虑是否可用
TotalMem = memory_management_struct.e820[memory_management_struct.e820_length].address + memory_management_struct.e820[memory_management_struct.e820_length].length;
//bits map construction init
// end_brk : 0x114a08 bits_map:0x115000
// 从内核程序结束地址 end_brk 起的4KB上边界对齐处 存入一个 bits_map,作为数组的基地址
memory_management_struct.bits_map = (unsigned long *)((memory_management_struct.end_brk + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
// bits_size &