dmesg -t | grep -i "page allocation failure" 是定位内核页分配失败的唯一有效方法,日志含 order:n(如 order:4 表示需16个连续页帧)和 mode 标志,反映内存碎片或整体不足;需结合 /proc/meminfo 与 vmstat 分析真实水位,并交叉验证 oom killer 记录以区分因果。

查 dmesg 里的 page allocation failure 记录
内存分配失败(尤其是内核无法满足页分配请求)会直接写入内核 ring buffer,dmesg 是唯一能拿到原始记录的工具。这类日志通常以 page allocation failure 开头,后面跟着 order 值(如 order:4 表示请求连续 2⁴=16 个页帧),说明内存碎片或整体不足。
执行以下命令快速定位:
dmesg -T | grep -i "page allocation failure"
常见错误行示例:
[Wed Jul 8 03:12:44 2026] some_module: page allocation failure: order:4, mode:0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_NOWARN), nodemask=(null)
-
order:4→ 请求 16 个连续物理页,失败说明内存严重碎片化或可用页不足 -
mode:0x40dc0→ 分配标志,GFP_KERNEL表示普通内核上下文分配,__GFP_NOWARN表示不触发额外警告 - 若同时看到
low memory或free:.*kB行,说明系统已接近内存耗尽临界点
结合 meminfo 和 vmstat 看内存状态上下文
单看 page allocation failure 只知道“失败了”,但不知道为什么失败。必须立刻抓取当时的内存水位和页回收压力。
执行这两条命令(建议在发现 failure 后 10 秒内运行):
cat /proc/meminfo | grep -E "^(MemAvailable|MemFree|PageTables|DirectMap)"
vmstat 1 5 | tail -n +2 | awk '{print $1,$4,$5,$6,$7,$15}'
-
MemAvailable比MemFree更关键:它代表可立即分配给新进程的内存,低于 100MB 就非常危险 -
PageTables过高(>500MB)说明进程虚拟地址空间映射开销大,可能有大量小对象或内存泄漏 -
vmstat输出中:free(空闲页)、buff(缓冲区)、cache(页缓存)、si/so(swap in/out)——如果si> 0,说明已在频繁换入,内存早已吃紧
确认是否被 OOM killer 杀过,再倒推分配失败原因
很多 page allocation failure 实际是 OOM killer 触发前的征兆。OOM 之后系统会尝试释放内存,但此时分配请求仍可能失败。
用这条命令交叉验证:
dmesg -T | grep -i "killed process\|out of memory" | tail -5
- 如果输出里有
Killed process,且时间戳比page allocation failure晚几秒,说明分配失败是 OOM 的结果而非原因 - 如果
page allocation failure出现在Killed process之前,大概率是驱动或内核模块在申请大块连续内存时失败(比如显卡驱动、DPDK 应用) - 注意 PID 字段:若 failure 日志里带模块名(如
nvidia、mlx5_core),优先检查对应驱动版本与当前内核是否匹配
避免误判:区分用户态 malloc 失败和内核页分配失败
page allocation failure 是内核级失败,和用户程序 malloc() 返回 NULL 完全不同。后者不会出现在 dmesg,而是在应用日志或 strace 中体现。
- 用户态内存不足 → 查
strace -e trace=brk,mmap,mremap -p PID,看系统调用是否返回-ENOMEM - 内核页分配失败 → 只会在
dmesg出现,且必含page allocation failure或Out of memory - 容器环境要额外注意:
docker run --memory=2g限制的是 cgroup memory limit,超限触发的是 cgroup OOM,日志格式和内核 OOM 不同,需查/sys/fs/cgroup/memory/docker/*/memory.oom_control
真正难排查的,是那些没留下 page allocation failure 字样的隐性失败——比如某些驱动在分配失败后静默降级,只报错不 panic,这时候得靠 perf record -e kmem:kmalloc,kmem:kfree 抓内存分配链路。











