导引:点亮什么、为什么需要它
001 的内核已经会说话,还把那张 E820 内存图整整齐齐 dump 到了串口上。可那只是"念出来",内核手里还是空的——它不知道哪块内存能用、哪块被占了,operator new 调一下还是原地 hlt。这一章,我们要给内核装一个物理内存管理器(PMM):用一张位图,把 E820 报告的可用内存变成"能分配、能回收"的一个个 4KB 物理页。从这以后,内核才算真正开始管资源。
这一章我们要点亮什么
目标很具体:实现一个 alloc_page() / free_page() 的分配器。内核想知道"给我一页空闲物理内存",PMM 就从位图里找一个空位、把那页的物理地址交出来;用完了 free_page 还回去,位图上那一位清掉。
它的依据是 001 已经收集好的 E820 内存图。PMM 在初始化时遍历这张图,把 BIOS 报告"可用"(type=1)的区域标记成可分配,把内核自己、bootloader、以及低 1MB 那些不能碰的地方标记成占用。之后 alloc_page 就在这张位图上做最朴素的"找第一个空位"(first-fit)。
做完之后,make run 的串口上会多出几行 [MINI] PMM: 的统计——内核多大、占了多少页、总共多少页可用。而 run-kernel-test 里的 test_pmm 会真去连续分配、回收、核对计数,确认这个分配器在边界上没漏。
为什么现在需要它
一个没有内存管理的内核能干什么?老实说,干不了什么正经事。后面要写的几乎每一样——进程的内核栈、页表、文件缓存、用户进程的地址空间——底下都需要"给我一页物理内存"这个原语。没有 PMM,这些都是空中楼阁。
那为什么是位图?因为它是物理页分配器里最简单、最直白的一种。每一页(4KB)对应位图里一个 bit:1 表示占用、0 表示空闲。要找空闲页,就在位图里扫第一个 0;要回收,就把对应 bit 清掉。这种分配器不快(分配是线性扫描),不省(128KB 位图管 4GB),但它正确性容易保证、行为容易理解,对一个教学内核来说,正是"先把路修通"的第一步。后面真要讲究性能,再换成 buddy 之类的——但那是后话,这一章我们只要"能正确地分、正确地收"。
外部依据:OSDev 的 Physical Memory Management / Page Frame Allocation 页对比了位图、栈式、buddy 这几类分配器的取舍;位图法以"实现简单、回收 O(1)、分配需扫描"著称,常被教学内核采用。