外部碎片导致大对象分配失败,需通过/proc/buddyinfo确认高阶空闲页缺失、dmesg查order报错、/proc/sys/vm/extfrag_threshold验证容忍度,并用echo 1 > /proc/sys/vm/compact_memory验证整理效果。

遇到“内存充足但大对象分配失败”,比如应用报 malloc 返回 NULL、内核日志出现 page allocation failure: order:X,而 free 显示仍有几百MB空闲——这大概率不是缺内存,而是外部碎片在作祟。排查要分三步走:确认是碎片、定位碎片位置、验证整理效果。
看 /proc/buddyinfo 判断是否真有外部碎片
这是最直接的证据。执行:
cat /proc/buddyinfo
输出按 NUMA 节点和内存区域(DMA、Normal、HighMem)列出各阶空闲页数。重点看高阶(order ≥ 5)是否为 0 或极低,同时低阶(order 0~3)数量却很多。例如:
Node 0, zone Normal 128 64 32 16 8 4 2 1 0 0 0
说明 29 = 512 页(2MB)、210(4MB)等大块全无,但小块充足——典型外部碎片。如果所有阶都接近 0,则更可能是内存真的耗尽或被 slab/ksm 等吃掉,需另查。
查 dmesg 和 /proc/sys/vm/extfrag_threshold 验证触发条件
运行:
dmesg -T | grep "page allocation failure"
找带 order: 的报错行,如 order:6 表示需要 26×4KB = 256KB 连续物理页。再确认系统对碎片的容忍度:
cat /proc/sys/vm/extfrag_threshold
默认值是 50,数值越低,内核越倾向于拒绝高阶分配(即更“怕”碎片)。若该值被调得很低(如 10),即使碎片不严重也可能频繁失败;若为默认值但仍持续报错,说明碎片确实已影响到分配底线。
结合 /proc/meminfo 和 slabtop 排除干扰项
碎片问题常被误判为内存泄漏或 slab 泄漏。先快速过筛:
- 对比
MemFree和DirectMap4k/DirectMap2M(在/proc/meminfo中):若前者高而后两者偏低,说明大量空闲页卡在无法用于大页或 DMA 的区域,指向碎片 - 运行
slabtop或cat /proc/meminfo | grep SReclaimable:若SReclaimable很高(几百 MB 以上),说明 slab 缓存膨胀,可能挤占了可移动页空间,加剧碎片化 - 检查
/proc/vmallocinfo:若 vmalloc 区域碎片严重(大量小段空闲),会影响内核模块加载和某些驱动的大块分配,虽不直接导致用户态 malloc 失败,但属于同源问题
尝试 compact_memory 并观察是否缓解
这是最轻量的验证手段。执行:
echo 1 > /proc/sys/vm/compact_memory
该操作会触发当前 NUMA 节点的内存规整(compaction),把可移动页搬走、合并空闲页。完成后立刻再看 /proc/buddyinfo ——如果高阶页数明显上升(如 order 9 从 0 变成 2),且后续大对象分配不再失败,就坐实了碎片问题。注意:此操作短时占用 CPU,生产环境慎用高频触发。











