“伙伴页分配把连续性细化为对齐幂二块的分裂与合并,能复算“总空闲8帧却没有8帧块”的状态。分区与保留预算再加入区域资格,解释有空闲仍拒绝某类请求;NUMA放置则在合法页框之间比较节点距离。三者…”
有8个空闲页框,不代表能交出一个连续8页的区域。物理页框分配理路物理页分配与安全回收Physical page allocator · Page frame free list把页框所有权、空闲链、发布前清零和最后使用者释放串成分配协议,解释它与用户堆对象分配的不同粒度。已经说明谁拥有一页、何时能重新使用它;本页再要求若干页连续,并研究怎样用简单的分裂与合并保留这种形状。
形式陈述
块的大小和起点一起受约束
教学池MEM-16有16个页框,相对编号为0到15。每页256字节;本页只用页数计量。整个池作为一个根块,所有块都在它的二叉分裂树中。一个 order
分配请求
每层有一份空闲块集合
直觉
为什么伙伴只差一个二进制位
order
起点
释放块时先找这个特定伙伴。只有伙伴也完整地空闲在同一层,才能从
这个限制使合并不必遍历所有相邻洞。起点、层数和空闲状态足以确定候选者;若空闲集合支持常数期望时间的查询与删除,最多经过
例子与边界
从一个16页块拿出3页
初始只有
| 动作 | 继续处理的块 | 新留下的空闲块 |
|---|---|---|
| 16对半成8 | ||
| 8对半成4 | ||
| 交付4页 | 不再分裂 |
实际请求3页,实际占用4页,块内有1页暂未用于这次请求。它是内部碎片,不是可被另一个页框请求随意取走的空闲页。若只统计用户有效需求,利用率是
总空闲8页,8页请求仍失败
现在重置实验:先把16页分成四个已经交付的4页块,起点依次0、4、8、12。释放起点0和8后,空闲集合为
随后释放起点4的块。它的伙伴
若最初改为释放4和8,虽然得到连续区间
异或公式不能越过池的边界
公式使用相对同一根块的编号。本例16页是一段对齐根块;现实内存可能有孔洞、不同节点或不同分区,不能看到绝对页号异或后的数字存在,就跨区域合并。必须先确认两块属于同一可合并池。池起点若不是相应幂二对齐,直接把绝对地址代入也需要重新证明。
重复释放、释放块中间地址、或用错误order释放,都会破坏覆盖不变量。多核情况下,检查伙伴和删除伙伴还需要作为一个同步操作,避免两个释放者同时把同一空闲块拿去合并。正确的数学伙伴关系不自动解决并发所有权。
推论与应用
两种碎片要分别修复
取
伙伴合并只能聚合已经空闲的正确兄弟。若想让分散自由页变成更大连续区域,可能需要迁移可移动的在用页,更新映射,再释放旧帧;不能移动的页又可能挡住整个过程。大页映射理路大页与TLB覆盖范围Huge pages · Superpages · TLB reach在数据全部驻留的模型中复算大页减少TLB未命中的条件,分开翻译覆盖、物理连续性、内部碎片与权限变更粒度。需要对齐连续物理区域时,就会遇到这项额外约束。
它与对象堆分配也分工不同:本页按整页幂二块交付,几十字节对象通常由上层分配器在已取得的页内组织。复算终点应同时交出空闲集合、每个已分配块的起点与order、以及总量守恒;只报一个“剩余8页”不足以说明下一项请求能否成功。
参考资料
- Arpaci-Dusseau与Arpaci-Dusseau,OSTEP, Ch.17, §17.4,“Buddy Allocation”:二分、伙伴合并与幂二取整。MEM-16轨迹、对齐反例与不变量检查为本页自定。
- Linux内核文档,“Physical Memory”,Zones → Zone structure →
free_area,查阅于2026-10-09:按order维护空闲区域的实际接口背景;本页不把简化集合等同于Linux全部快速路径。