物理内存管理 - 常见错误
错误 1:位图初始化错误
症状
所有内存分配失败,或分配到已使用的内存。
原因
位图未正确初始化。
解决方案
初始化策略:先全部标记为已使用(0xFF),然后标记已知可用区域为空闲。
memset(bitmap, 0xFF, BITMAP_SIZE); // 全部标记已使用
pmm_mark_region_free(0x100000, available); // 只释放确认可用的区域错误 2:分配到内核代码所在的内存
症状
分配内存后,内核崩溃或行为异常。
原因
没有保护内核占用的物理内存。
解决方案
确保内核区域在位图中标记为已使用:
extern uint32_t _kernel_end; // 链接脚本中定义
pmm_mark_region_used(0x1000, (uint32_t)&_kernel_end - 0x1000);错误 3:位运算错误
症状
释放一个帧影响了相邻帧的状态。
原因
位操作时,frame/8 和 frame%8 混淆,或移位方向错误。
解决方案
// 正确的位操作
static inline void bitmap_set(uint32_t frame) {
bitmap[frame / 8] |= (1 << (frame % 8)); // 设置
}
static inline void bitmap_clear(uint32_t frame) {
bitmap[frame / 8] &= ~(1 << (frame % 8)); // 清除
}错误 4:双重释放
症状
空闲帧计数异常(超过总帧数)。
原因
同一个帧被释放了两次。
解决方案
void pmm_free_frame(uint32_t phys_addr) {
uint32_t frame = ADDR_TO_FRAME(phys_addr);
if (!bitmap_test(frame)) {
// 已经是空闲的,可能是bug
screen_printf("[PMM] Warning: double free at 0x%x\n", phys_addr);
return;
}
bitmap_clear(frame);
used_frames--;
}错误 5:kmalloc返回未对齐地址
症状
页表操作失败,因为地址不是4KB对齐。
原因
使用了普通kmalloc而非页对齐版本。
解决方案
// 页表、页目录等必须使用对齐版本
page_directory_t *dir = kmalloc_aligned(sizeof(page_directory_t));