物理内存严重碎片化是“内存够但拼不出大块”,表现为echo 20 > /proc/sys/vm/nr_hugepages失败、dmesg频繁报page allocation failure: order:X、/proc/buddyinfo显示高阶页为0,三者共现即可锁定外碎片问题。

物理内存严重碎片化不是“内存不够”,而是“内存够但拼不出大块”。echo 20 > /proc/sys/vm/nr_hugepages 失败、dmesg 里反复出现 page allocation failure: order:X、/proc/buddyinfo 显示高阶空闲页为 0,这三者同时出现,基本可以锁定是外碎片问题。
看 /proc/buddyinfo 确认碎片程度
这是最直接的证据。执行:cat /proc/buddyinfo
输出每行类似:Node 0, zone DMA 12 5 3 1 0 0 0 0 0 0 0
从左到右对应 order 0(4KB)到 order 10(4MB)。重点看最后几列:
- 如果 order 9(2MB)或 order 10(4MB)全为 0,而 order 0~4 的数字很大,说明空闲页充足但高度离散
- NUMA 多节点系统要逐个 node 检查,
Node 1可能已严重碎片化,而Node 0还很健康 - 注意 zone 区分:DMA、DMA32、Normal 各自独立管理,
order:9分配失败若发生在 DMA32 zone,说明该 zone 内部碎片,和其他 zone 无关
查 dmesg 锁定失败上下文
碎片导致的分配失败一定会留下内核痕迹:
- 运行
dmesg -T | grep -i "page allocation failure",找带order:的行,例如page allocation failure: order:5表示需要 32×4KB = 128KB 连续页 - 注意后面是否跟有
gfp_mask:,比如GFP_DMA或GFP_MOVABLE,这说明请求有迁移类型限制,会进一步加剧碎片敏感度 - 如果同一 order 失败高频出现(>10 次/分钟),且伴随
__alloc_pages_slowpath调用栈,说明内核已在反复重试并失败
用 /proc/sys/vm/extfrag_threshold 判断内核是否“太挑”
这个阈值控制内核对碎片的容忍度。默认是 50,数值越小,内核越容易拒绝高阶分配:
- 执行
cat /proc/sys/vm/extfrag_threshold查当前值 - 若值被调低(如设为 10),即使实际碎片不严重,也会频繁报错;此时可临时提高(
echo 75 > /proc/sys/vm/extfrag_threshold)测试是否缓解 - 但要注意:提高阈值只是“放宽检查”,不能解决真实碎片;若提高后仍失败,说明物理连续性确实已崩坏
手动触发 compaction 并观察效果
Linux 不提供“一键整理”,但可通过 compaction 强制内核尝试合并空闲页:
- 对单个 NUMA node 手动 compact:
echo 1 > /proc/sys/vm/compact_memory(慎用,会短时阻塞分配) - 更安全的做法是启用自动 compact:确保
CONFIG_COMPACTION=y(现代内核默认开启),并确认/proc/sys/vm/compact_unevictable_allowed为 1(允许整理不可回收页区域) - 触发后立刻再查
/proc/buddyinfo,若高阶页数量回升(比如 order 9 从 0 变成 2),说明 compact 成功;若无变化,大概率存在大量UNMOVABLE页卡死,需查/proc/pagetypeinfo或卸载相关内核模块
真正难处理的从来不是“怎么触发整理”,而是识别哪些页根本无法移动——比如某些驱动申请的 DMA 缓冲区、内核模块的 vmalloc 区域、或者被 mlock() 锁住的用户态内存。这些才是碎片化的“钉子户”,删不掉、搬不动,只能靠重启模块或服务释放。











