Linux 内核态崩溃的常见原因

12次阅读

内核态崩溃主要由非法内存访问、同步失效、内存管理异常、时间子系统溢出及kdump失效引发。典型如NULL指针解引用、slab corruption、watchdog超时、jiffies溢出,以及crashkernel预留不足导致日志丢失。

Linux 内核态崩溃的常见原因

内核态崩溃几乎总是由不可恢复的非法内存访问或同步失效引发,比如空指针解引用、use-after-free、soft/hard lockup 或 watchdog 超时 —— 这些不是“程序出错”,而是内核失去了对系统状态的控制权。

驱动或模块触发的 NULL pointer dereference

这是最典型的内核态崩溃起因,尤其在自研/第三方驱动中高频出现。错误日志里常看到:Unable to handle kernel NULL pointer dereference at 00000000 或类似地址(如 000001db)。它意味着某段内核代码试图读写一个根本没初始化或已被释放的指针。

  • 常见场景:设备热插拔未做 dev->driver 检查、workqueue 回调中直接访问已注销的设备结构体、中断上下文里调用可能 sleep 的函数
  • 容易踩的坑:认为“只要没 panic 就安全”,但 bug()WARN_ON() 触发后继续执行,往往几秒内就演变成 oops → panic
  • 验证方式:用 crashcrash_arm 打开 vmcore,执行 bt回溯,再用 dis 反汇编出错指令附近代码,定位到具体行(例如 mmc_notify_sc_work+0x1c/0xb4

内存管理异常:OOM Killer 误杀 or page fault 失控

内核态崩溃不等于用户态内存耗尽,但当内存子系统本身出问题时(如 slab corruption、page refcount underflow),会直接导致 panic。典型标志是日志中出现 kernel BUG at mm/slub.cBad pagetable

  • 关键区别:用户进程被 OOM Killer 杀掉(dmesg -T | grep "killed process")≠ 内核崩溃;但若 slab_alloc_node 返回 NULL 后未检查就直接解引用,就会崩
  • 配置影响:开启 CONFIG_DEBUG_SLABCONFIG_KASAN 能提前捕获 use-after-free,但会显著降低性能,生产环境慎用
  • 硬件关联:memtest86+ 必跑 —— 很多看似“随机”的 slab 错误,根源是某条内存条 ECC 校验失败后静默改写了元数据

调度与时间子系统溢出:watchdog timeout / jiffies overflow

linux 内核依赖精确的时间计量维持调度公平性和 watchdog 健康检查。一旦 jiffies 计数器溢出(32 位系统约 497 天)、或高负载下 hrtimer 队列严重积压,watchdog 线程检测不到预期 tick,就会强制 panic。

  • 典型现象:日志中出现 watchdog: BUG: soft lockup - CPU#X stuck for Ns!Hard LOCKUP,且无明显模块名指向
  • 真实案例:某分布式文件系统在持续高 I/O + 高并发定时任务场景下,tick_do_update_jiffies64 因锁竞争延迟超阈值,触发 watchdog 中断嵌套死锁
  • 排查要点:检查 /proc/timer_list 是否有大量 pending timer;对比 cat /proc/sys/kernel/watchdog_thresh 和实际负载,避免阈值设得过低

kdump 未启用或 crashkernel 预留失败:日志丢失即失联

很多团队花几天排查崩溃,最后发现根本没拿到有效日志 —— 不是因为没发生,而是 kdump 没生效。这会让所有分析退回到“猜”阶段。

  • 必须验证的三件事:cat /proc/cmdline 看是否含 crashkernel=systemctl status kdump 是否 active;ls /var/crash/ 下是否有最新时间戳的 vmcore
  • 常见配置陷阱:crashkernel=auto 在某些 ARM64 服务器上会预留不足(如只分 64M),导致 kdump 内核启动失败;应显式指定,如 crashkernel=256M@16M
  • 云环境特例:AWS/Aliyun 的部分实例类型禁用 kexec,kdump 无法工作,此时唯一可靠日志来源是串口控制台输出(需提前配置 console=ttyS0,115200n8

真正棘手的内核崩溃,往往藏在“看起来正常”的边界条件里:CPU 频率动态调节干扰了 timer 精度、NUMA 节点间内存迁移引发 refcount 竞态、甚至 bios 中某个电源管理选项关闭了 APIC 时钟源。所以别只盯着 dmesg —— 先确认你有没有拿到那块真实的 vmcore,再谈破案。

text=ZqhQzanResources