3、Hung Task检测机制:内核hung_task检测模块、NMI Watchdog与Soft Lockup、Hard Lockup的区别
在Linux内核中,当调度器或某个执行路径长时间无法响应调度事件时,系统可能陷入“假死”状态。为了及时发现并定位这类故障,内核提供了三种不同粒度的检测机制:Hung Task、Soft Lockup 和 Hard Lockup。它们分别从进程级、内核抢占级和CPU中断级进行监控,构成了调度器故障定位的“三道防线”。
3.1 Hung Task检测模块
Hung Task机制是内核中专门用于检测处于不可中断睡眠状态(D状态)且长时间未调度的进程。其核心原理是内核线程 khungtaskd 周期性扫描所有进程,检查是否有进程在D状态下停留超过预设阈值。
关键参数:
kernel.hung_task_timeout_secs:默认120秒,超过此时间未调度的D状态进程将被判定为Hung Task。kernel.hung_task_warnings:默认10次,控制日志输出频率,防止日志风暴。kernel.hung_task_panic:默认0,若设置为1,检测到Hung Task时直接触发panic。
当检测到Hung Task时,内核会在 /var/log/messages 或通过 dmesg 输出类似以下日志:
[ 1234.567890] INFO: task kworker/u:2:456 blocked for more than 120 seconds.
[ 1234.567891] Tainted: G O
[ 1234.567892] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1234.567893] kworker/u:2 D 0 456 2 0x00000000
[ 1234.567894] Call Trace:
[ 1234.567895] __schedule+0x2d0/0x8a0
[ 1234.567896] schedule+0x35/0x90
[ 1234.567897] io_schedule+0x15/0x40
[ 1234.567898] wait_on_page_bit_common+0x1a0/0x3e0
[ 1234.567899] __lock_page+0x80/0xb0
[ 1234.567900] filemap_fault+0x3a0/0x7a0
[ 1234.567901] __do_fault+0x38/0x120
[ 1234.567902] handle_mm_fault+0x1b0/0x300
[ 1234.567903] do_page_fault+0x2e0/0x4f0
[ 1234.567904] page_fault+0x1e/0x30
排查要点:日志中的
Call Trace 是定位阻塞点的关键。常见的阻塞点包括 wait_on_page_bit(页缓存等待)、inode_sleep(inode锁等待)、rpc_wait(NFS RPC等待)等。结合 /proc/<pid>/stack 可以实时查看进程内核栈。
3.2 Soft Lockup与Hard Lockup
Soft Lockup和Hard Lockup是内核用于检测CPU是否“卡死”的机制,它们依赖于NMI(Non-Maskable Interrupt,不可屏蔽中断)和周期性时钟中断。
| 特性 | Soft Lockup | Hard Lockup |
|---|---|---|
| 检测对象 | 内核态是否长时间禁止抢占(关闭内核抢占) | CPU是否响应中断(NMI) |
| 触发条件 | 单个CPU上超过20秒未发生调度切换 | 单个CPU上超过20秒未响应NMI中断 |
| 检测手段 | 高精度定时器(hrtimer) + 内核线程 watchdog | NMI中断 + 硬件性能计数器(PMU) |
| 典型原因 | 自旋锁死循环、关抢占后执行耗时操作 | 中断被长时间屏蔽、硬件故障、CPU挂起 |
| 内核参数 | kernel.softlockup_panic |
kernel.hardlockup_panic |
| 日志特征 | watchdog: BUG: soft lockup - CPU#0 stuck for 22s! |
watchdog: BUG: hard lockup - CPU#0 stuck for 22s! |
重要区别:Soft Lockup发生时,系统可能还能响应部分中断(如NMI),因此可以通过NMI触发panic或输出调试信息。而Hard Lockup发生时,CPU完全无法响应任何中断,包括NMI,此时只能依赖硬件看门狗(如HPET或外部WDT)来复位系统。
3.3 三种检测机制的关系与对比
从检测层次上看,Hung Task、Soft Lockup和Hard Lockup构成了从进程到CPU的完整监控链:
3.4 检测机制的配置与调优
在实际生产环境中,需要根据业务场景合理配置这三种检测机制的参数,避免误报或漏报:
| 参数 | 默认值 | 推荐生产值 | 说明 |
|---|---|---|---|
kernel.hung_task_timeout_secs |
120 | 300 | 对于IO密集型业务(如数据库),适当增大避免误报 |
kernel.hung_task_panic |
0 | 0 | 生产环境建议关闭,避免因IO抖动导致系统panic |
kernel.softlockup_panic |
0 | 1 | 建议开启,Soft Lockup通常意味着内核bug |
kernel.hardlockup_panic |
0 | 1 | 建议开启,Hard Lockup意味着CPU完全失控 |
kernel.watchdog_thresh |
10 | 10 | Soft/Hard Lockup的超时阈值(秒),实际检测为2倍值 |
调优实践:对于运行在虚拟化环境或云主机上的系统,由于存在CPU抢占(Steal Time),建议将
kernel.watchdog_thresh 适当增大至20-30秒,避免因宿主机调度延迟导致误报Soft Lockup。
3.5 日志分析实战:从dmesg中识别故障类型
当系统出现异常时,dmesg 日志是定位问题的第一手资料。以下通过三个典型日志片段,展示如何区分三种检测机制的触发场景:
- Hung Task日志特征:
[ 5000.123456] INFO: task mysqld:12345 blocked for more than 120 seconds. [ 5000.123457] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 5000.123458] mysqld D 0 12345 1 0x00000000 [ 5000.123459] Call Trace: [ 5000.123460] __schedule+0x2d0/0x8a0 [ 5000.123461] schedule+0x35/0x90 [ 5000.123462] io_schedule+0x15/0x40 [ 5000.123463] wait_on_page_bit_common+0x1a0/0x3e0→ 进程处于D状态,等待页缓存IO完成,属于IO阻塞。
- Soft Lockup日志特征:
[ 6000.654321] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [kworker/2:1:456] [ 6000.654322] Modules linked in: ... [ 6000.654323] CPU: 2 PID: 456 Comm: kworker/2:1 Tainted: G O [ 6000.654324] RIP: 0010:_raw_spin_lock+0x1c/0x30 [ 6000.654325] Call Trace: [ 6000.654326] spin_lock+0x2a/0x30 [ 6000.654327] ext4_do_update_inode+0x1e0/0x2a0→ CPU#2在自旋锁上卡住超过22秒,内核抢占被关闭,属于内核态死锁。
- Hard Lockup日志特征:
[ 7000.111111] watchdog: BUG: hard lockup - CPU#3 stuck for 22s! [swapper/3:0] [ 7000.111112] Modules linked in: ... [ 7000.111113] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G O [ 7000.111114] RIP: 0010:native_safe_halt+0x6/0x10→ CPU#3在空闲循环中无法响应NMI,可能是硬件故障或中断控制器异常。
故障定位三步法:
- 看类型:日志开头是
INFO: task(Hung Task)、soft lockup还是hard lockup。 - 看CPU和进程:锁定出问题的CPU编号和进程名/进程ID。
- 看调用栈:分析
Call Trace中的最后一个内核函数,定位阻塞点。
3.6 三种机制的协同工作流程
当系统出现故障时,三种检测机制可能同时触发,但它们的触发顺序和严重程度不同。以下流程图展示了典型的协同工作场景:
实战提醒:在排查系统“假死”问题时,如果同时看到Hung Task和Soft Lockup日志,优先分析Soft Lockup的调用栈,因为它通常揭示了导致所有进程阻塞的根本原因(如全局自旋锁死锁)。Hung Task往往是Soft Lockup的“症状”而非“病因”。