2. 内核异常分类:Oops、Panic、Kernel Bug、Soft Lockup、Hard Lockup、Deadlock
Linux 内核在运行过程中可能遭遇多种异常状态。准确识别异常类型是定位根因的第一步。本章系统梳理六类核心内核异常,从触发机制、典型现象到诊断切入点,为后续 ftrace 与栈回溯联合分析奠定基础。
2.1 异常分类总览
下表从触发条件、系统行为、可恢复性三个维度对比六类异常,帮助建立全局认知。
| 异常类型 | 触发条件 | 系统行为 | 可恢复性 | 典型日志特征 |
|---|---|---|---|---|
| Oops | 内核访问非法地址、空指针解引用 | 仅杀死当前进程,系统继续运行 | 部分可恢复 | Unable to handle kernel NULL pointer dereference |
| Panic | 致命错误(如内核堆栈溢出、关键数据结构损坏) | 系统立即停止,打印调用栈后挂起或重启 | 不可恢复 | Kernel panic - not syncing |
| Kernel Bug | 内核代码逻辑断言失败 | 打印 BUG 信息,可能触发 Panic 或 Oops | 视上下文而定 | ------------[ cut here ]------------ |
| Soft Lockup | CPU 在软中断或 spinlock 上长时间自旋(>20s) | 内核触发软锁检测,打印 CPU 栈回溯 | 可恢复(若锁释放) | BUG: soft lockup - CPU#X stuck for 22s! |
| Hard Lockup | CPU 在关中断状态下死循环(NMI 无法被响应) | NMI 看门狗触发,打印寄存器与栈信息 | 不可恢复 | NMI watchdog: BUG: hard lockup on CPU#X |
| Deadlock | 两个或多个任务互相等待对方持有的锁 | 任务永久阻塞,系统吞吐下降,可能触发 Lockdep 告警 | 可恢复(若外部干预) | ============================================WARNING: possible recursive locking detected |
诊断优先级提示: 在异常定位中,Oops 和 Panic 是最常见的两类直接崩溃异常,通常伴随完整的栈回溯信息,是 ftrace 联合分析的首选场景。Soft/Hard Lockup 和 Deadlock 属于“活锁”类异常,系统未立即崩溃但行为异常,需要借助 ftrace 的
function_graph 和 lock 事件进行时序分析。
2.2 Oops 与 Panic:内核崩溃的两级响应
2.2.1 Oops 机制详解
Oops 是内核从异常中尝试恢复的第一道防线。当内核检测到非致命错误(如访问 NULL 指针、使用已释放的内存)时,会执行以下流程:
- 异常触发:CPU 产生缺页异常或保护异常,进入内核异常处理路径。
- 信息收集:内核打印错误描述、CPU 寄存器值、当前进程的栈回溯。
- 进程隔离:向当前进程发送
SIGKILL信号,仅终止该进程。 - 系统继续:内核调度器选择下一个进程运行,系统整体不受影响。
关键诊断信息: Oops 日志中的
RIP(指令指针寄存器)和 Call Trace 是定位故障函数的直接线索。结合 ftrace 的 function_graph 可以还原故障发生前的函数调用序列。
以下是一个典型的 Oops 日志片段:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffffa0002000>] my_driver_write+0x20/0x50 [my_module]
PGD 0 P4D 0
Oops: 0002 [#1] SMP
CPU: 2 PID: 1234 Comm: test_app Tainted: P O
RIP: 0010:my_driver_write+0x20/0x50
Call Trace:
<IRQ>
[<ffffffff81234567>] vfs_write+0x123/0x200
[<ffffffff81234589>] ksys_write+0x45/0x90
[<ffffffff81001234>] do_syscall_64+0x5c/0x110
</IRQ>
2.2.2 Panic 机制详解
Panic 是内核的最终异常响应。当内核检测到无法恢复的致命错误时,会调用 panic() 函数,执行以下操作:
- 停止所有其他 CPU:通过
smp_send_stop()发送停止信号。 - 打印 Panic 信息:包含错误原因、当前 CPU 寄存器、完整栈回溯。
- 触发 kdump(若配置):启动捕获内核,保存崩溃转储文件。
- 系统挂起或重启:根据
panic_timeout参数决定行为。
注意: Panic 发生后,系统不再可用。此时 ftrace 的 trace buffer 可能尚未刷新到磁盘。建议在启动参数中配置
ftrace_dump_on_oops=1,使内核在 Panic 时自动将 ftrace 缓冲区内容输出到控制台或串口。
2.3 Kernel Bug:内核自检断言
BUG() 和 BUG_ON() 是内核开发者嵌入代码的显式断言宏。当条件不满足时,内核会打印 ------------[ cut here ]------------ 标记,并输出调用栈。Kernel Bug 的行为取决于内核配置:
- CONFIG_BUG=y:触发 Oops,系统继续运行。
- CONFIG_BUG_ON_PANIC=y:直接触发 Panic。
Kernel Bug 通常指示内核代码逻辑错误,而非硬件问题。诊断时重点关注 BUG() 所在函数及其调用路径。
2.4 Soft Lockup 与 Hard Lockup:CPU 无响应检测
2.4.1 检测机制对比
| 特性 | Soft Lockup | Hard Lockup |
|---|---|---|
| 检测方式 | 高精度定时器(hrtimer)周期性检查 | NMI 看门狗(NMI watchdog) |
| 中断状态 | 中断可响应 | 中断被关闭 |
| 典型原因 | spinlock 长时间持有、软中断死循环 | 关中断后死循环、硬件故障 |
| 诊断工具 | ftrace function_graph + irqsoff tracer |
NMI 栈回溯 + ftrace nmi 事件 |
2.4.2 Soft Lockup 诊断流程
- 查看
/var/log/messages或dmesg中的soft lockup日志。 - 记录
Call Trace中卡住的函数。 - 使用 ftrace 的
irqsofftracer 测量中断关闭时间。 - 使用
function_graph追踪卡住函数的调用链。
2.5 Deadlock:锁依赖循环
Deadlock 是最隐蔽的内核异常之一。Linux 内核通过 Lockdep(Lock Dependency Validator)在运行时检测潜在的死锁。Lockdep 会在以下情况输出告警:
- 检测到锁的循环依赖(ABBA 模式)。
- 检测到锁的递归获取(同一线程重复获取同一锁)。
- 检测到锁的释放顺序与获取顺序不一致。
Lockdep 告警日志包含完整的锁依赖链和当前任务的栈回溯,是诊断死锁的核心依据。
ftrace 联合诊断技巧: 对于 Deadlock 场景,启用 ftrace 的
lock 事件组(echo 1 > /sys/kernel/debug/tracing/events/lock/enable),可以记录每次锁的获取和释放操作,精确还原锁的时序关系。
2.6 异常分类关系图
下图展示了六类内核异常在系统响应层级上的关系,以及 ftrace 在不同异常类型中的诊断切入点。
2.7 异常类型与诊断工具匹配表
在实际调试中,根据异常类型选择合适的 ftrace tracer 和事件组,可以大幅提升定位效率。
| 异常类型 | 首选 ftrace tracer | 辅助事件组 | 关键分析指标 |
|---|---|---|---|
| Oops | function_graph |
kmem(内存分配事件) |
RIP 所在函数、调用路径、内存操作序列 |
| Panic | function_graph + ftrace_dump_on_oops |
printk 事件 |
Panic 前最后执行的函数、内核消息序列 |
| Kernel Bug | function_graph |
bug 事件(需内核支持) |
BUG 触发点、条件判断上下文 |
| Soft Lockup | irqsoff / preemptoff |
timer 事件 |
中断关闭时长、spinlock 持有时间 |
| Hard Lockup | nmi 事件 |
function_graph(需 NMI 安全) |
NMI 触发时的指令指针、寄存器状态 |
| Deadlock | lock 事件组 |
function_graph + wakeup |
锁获取/释放时序、任务唤醒链 |
实战建议: 在开发或测试环境中,建议始终开启
CONFIG_LOCKDEP 和 CONFIG_FTRACE,并设置 ftrace_dump_on_oops=1。这样在发生 Oops 或 Panic 时,可以同时获取栈回溯和 ftrace 时序数据,为联合诊断提供完整素材。