强开大页内存引发内核死锁的本质是hugetlb_lock、zone->lock与mmap_sem多层嵌套锁竞争,叠加HugePages_Free=0而HugePages_Rsvd>0时的循环等待;典型表现为khugepaged卡死、进程D状态、dmesg报page allocation failure或lockdep警告。

强开大页内存(HugeTLB)引发的内核内存分配死锁,本质是内存管理子系统在高压下因锁竞争与资源耗尽陷入循环等待。这类故障常表现为系统负载飙升、khugepaged卡死、进程长时间处于 D 状态、cat /proc/meminfo 显示 HugePages_Free 为 0 但 HugePages_Rsvd 持续不归零,且 dmesg 出现 page allocation failure 或 lockdep 报警。排查需聚焦“大页预分配路径”与“常规页分配器”的锁交叠点。
确认是否为大页相关死锁
先快速验证问题根源是否指向 HugeTLB:
- 运行
grep -i "huge" /proc/meminfo,重点看HugePages_Total、HugePages_Free、HugePages_Rsvd。若Rsvd > 0且Free == 0,说明有进程已预留大页但未能成功分配物理页,这是典型卡点 - 执行
cat /proc/sys/vm/nr_hugepages和cat /proc/sys/vm/nr_overcommit_hugepages,确认是否人为强制设置了过大值(如直接写入 1024+),尤其在物理内存不足时极易触发 - 检查
dmesg -T | grep -i -E "(huge|alloc|oom|lockdep|hung_task)",关注是否有BUG: sleeping function called from invalid context(常见于在中断上下文调用alloc_huge_page)、lockdep: DETECTED OUT OF ORDER LOCKING或hung_task: blocked tasks提示
定位阻塞在哪个锁路径上
大页分配涉及多层锁:hugetlb_lock(全局大页池锁)、zone->lock(内存区锁)、mmap_sem(进程地址空间锁),三者嵌套极易形成 AB-BA。关键操作如下:
- 用
crash工具加载 ramdump 后,执行ps -G | grep "UN"找出不可中断状态进程,再对每个 PID 执行bt -v,观察堆栈是否停在alloc_huge_page→__alloc_pages_nodemask→get_page_from_freelist链路中,尤其是是否卡在spin_lock(&zone->lock)或mutex_lock(&hugetlb_lock) - 若启用过
CONFIG_LOCKDEP=y,检查/proc/lockdep和/proc/lockdep_chains,搜索关键词hugetlb、zone、mmap_sem,确认是否存在hugetlb_lock --> zone->lock与zone->lock --> hugetlb_lock的逆向依赖环 - 查看
/proc/locks中类型为FLOCK或POSIX的条目是否异常增多,有时用户态大页映射(MAP_HUGETLB)会间接阻塞内核线程清理路径
检查大页预分配与 overcommit 配置冲突
线上最常见诱因是配置失当而非代码缺陷:
-
nr_hugepages设为固定值(如 512)后,系统启动时尝试一次性分配全部大页,若物理内存碎片化严重或被其他模块(如 CMA、GPU DRM)提前占用,会导致hugetlb初始化失败并长期持有hugetlb_lock重试,阻塞后续所有大页请求 -
nr_overcommit_hugepages被设为非零值(如 256)时,允许进程“超量预约”大页,但实际分配仍受限于空闲大页数。当多个进程并发mmap(MAP_HUGETLB),HugePages_Rsvd累加却无法兑现,khugepaged在后台反复扫描hugetlb全局链表并争抢hugetlb_lock,加剧锁竞争 - 对比
cat /sys/kernel/mm/hugepages/hugepages-2048kB/free与surplus值:若free == 0且surplus > 0,说明内核正试图回收常规页转为大页,但被pagevec或lru_lock卡住,此时需查slabinfo是否page->_refcount异常高
临时缓解与根治建议
线上优先保服务,再做深度修复:
- 立即执行
echo 0 > /proc/sys/vm/nr_hugepages清空预分配大页池(注意:已映射的大页不受影响,但可阻止新卡死);若失败,用echo 1 > /proc/sys/vm/drop_caches释放 pagecache,辅助khugepaged回收 - 禁用 overcommit:
echo 0 > /proc/sys/vm/nr_overcommit_hugepages,避免预留膨胀;同时检查应用是否滥用MAP_HUGETLB | MAP_POPULATE组合,该组合在缺页时同步分配,极易阻塞主线程 - 根治需从配置入手:生产环境应关闭静态大页(
nr_hugepages=0),改用透明大页(transparent_hugepage=always/madvise),由内核按需合并;若必须用显式大页,应通过libhugetlbfs+mmap按需申请,并设置合理max_huge_pages上限


















