Skip to content

设计图:一位一页的位图

先看位图这个数据结构怎么把物理内存"拍扁"成一张表:

text
物理内存(每页 4KB)
  页0    页1    页2    页3   ...   页(4GB/4KB-1)= 1M 页
   │      │      │      │            │
   ▼      ▼      ▼      ▼            ▼
 bit0   bit1   bit2   bit3   ...   bit(1M-1)
  └──────────── 一位一页,装进 128KB 的 s_bitmap ────────────┘
   1=占用  0=空闲

MAX_MEMORY = 4_GBPAGE_SIZE = 4_KB,所以最多 MAX_PAGES = 1M 页,位图 BITMAP_SIZE = 1M/8 = 128KB(每字节 8 页)。这个 128KB 的数组是 PMM 的全部状态,放在内核的 .bss 里。

再看初始化的思路。这里有个反直觉但很稳的设计:先把所有页都标成"占用",再把能用的"挖"出来。这比"先全空、再标占用"安全——默认拒绝,只对确认可用的开绿灯,漏标顶多是少分到内存,绝不会把保留区误分出去:

text
init(boot_info):
  ① 位图全置 1(全占用)           ← 默认拒绝
  ② 遍历 E820:
       type==1(可用)的区域 →
         滤掉低 1MB、页对齐 → 标 free(挖出来)
  ③ 内核自身区域 → 标 used(保护)
  ④ bootloader 区 0x0–0x10000 → 标 used(保护)

alloc/free 则是在这张表上做最简单的位操作:

text
alloc_page():  扫描位图找第一个 0 → 置 1 → 返回 该页物理地址(page_idx × 4KB)
               扫不到 → 返 0(OOM)
free_page(p):  p/4KB 得 page_idx → 该 bit 清 0

035_multi_terminal-45-gf25de18 · f25de18 · 2026-08-04