hardlockup && softlockup && hungtask

这三者是 Linux 内核在不同层面上的 "卡死"检测机制 ,主要区别在于 故障表现、影响范围和检测手段 :

1. Soft Lockup(软死锁)

核心特征:CPU 在"干活"但"不调度"

维度 说明
状态 某个 CPU 长时间(默认 20s)执行内核代码,不调用 schedule() 释放 CPU
中断 ✅ 正常响应(timer tick 仍能触发)
抢占 ❌ 可能禁用了抢占,或陷入死循环
症状 系统部分卡顿,其他 CPU 可能正常,SSH 可能能连接但响应慢

典型场景:

// 1. 长时间关闭抢占
preempt_disable();
while (1);  // 死循环,但不会触发硬死锁

// 2. 计算密集型内核操作(如过大的 hash table 遍历)
// 3. spin_lock 持有者被抢占(CONFIG_PREEMPT 关闭时)

检测原理:
每个 CPU 有一个高优先级的 watchdog/x 线程,定期(每秒)更新时间戳。如果某个 CPU 的 watchdog 线程超过 watchdog_thresh(默认 20s)未运行,则触发 soft lockup。

# 日志特征
softlockup: hung tasks: 123
Watchdog detected hard LOCKUP on cpu 0  # 注意:这里实际指 soft lockup

2. Hard Lockup(硬死锁)

核心特征:CPU 连中断都不响应了

维度 说明
状态 CPU 长时间(默认 20-40s)关闭中断,定时器中断无法处理
中断 ❌ 被屏蔽(local_irq_disable() 或 spin_lock_irq)
抢占 通常也禁用
症状 该 CPU 完全冻结,系统时钟停止,网络中断(若在该 CPU),可能触发 NMI panic

典型场景:

// 1. 长时间持有关中断锁
spin_lock_irq(&lock);
msleep(100000);  // 在 atomic 上下文睡眠(严重 bug)
spin_unlock_irq(&lock);

// 2. 中断处理程序死循环
irq_handler() {
    while (1);  // 永远出不去
}

检测原理:
必须使用 NMI(不可屏蔽中断),因为普通 timer 中断已被屏蔽。NMI watchdog(perf 硬件或 lapic)定期检查每个 CPU 的 hrtimer_interrupts 计数,若长时间未增加则判定为 hard lockup。

# 日志特征
Watchdog detected hard LOCKUP on cpu 2
RIP: 0010:buggy_function+0x45/0x80  # 显示卡死的指令地址

3. Hung Task(任务挂起)

核心特征:进程卡在不可中断睡眠(D 状态)

维度 说明
范围 进程级别(非 CPU 级别)
状态 进程长时间(默认 120s)处于 TASK_UNINTERRUPTIBLE(D 状态)
中断 ✅ CPU 正常,中断正常,调度正常
症状 单个进程无法 kill(包括 kill -9),ps 看到 STAT 为 D,系统可能仍可用

典型场景:

// 1. I/O 死锁:等待磁盘响应但控制器已挂
vfs_read() -> ... -> scsi_execute() -> wait_for_completion(D状态)

// 2. 网络文件系统(NFS)故障,服务器不可达
// 3. 驱动 bug:忘记 wake_up() 等待队列

检测原理:
内核线程 khungtaskd 定期(每 2 秒)扫描所有 D 状态进程,检查 task->timestamp(进入 D 状态的时间)。若超过 hung_task_timeout_secs(默认 120s),则打印警告。

# 日志特征
INFO: task kworker/u16:2:12345 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
kworker/u16:2   D    0 12345      2 0x80000000
Call Trace:
 __schedule+0x2a1/0x850
 schedule+0x46/0xb0
 ...

对比总结

特性 Soft Lockup Hard Lockup Hung Task
检测对象 CPU 核心 CPU 核心 单个进程
中断状态 开启 关闭 开启
调度状态 不调度 不调度 被调度但睡眠
能否 kill -9 N/A(CPU 问题) N/A 不能(D 状态)
检测器 watchdog/x 线程 NMI 硬件 khungtaskd 线程
默认超时 20s 20-40s(2×soft) 120s
触发 panic 可选 可选(建议开启) 可选(通常不开启)
典型原因 死循环、大锁、算法复杂度过高 关中断锁死循环、中断 handler bug I/O 死锁、驱动 wait_event 未唤醒

配置参数

# /etc/sysctl.conf 或 /proc/sys/kernel/

# Soft lockup
kernel.watchdog = 1                    # 总开关(同时控制 soft/hard)
kernel.watchdog_thresh = 20            # 超时秒数

# Hard lockup(依赖 soft lockup 开启)
kernel.nmi_watchdog = 1                # 1=启用, 0=禁用
kernel.hardlockup_panic = 1            # 检测到时是否 panic(建议生产环境开启)

# Hung task
kernel.hung_task_timeout_secs = 120    # 0=禁用检测
kernel.hung_task_panic = 0             # 是否 panic(通常保持 0,仅记录)
kernel.hung_task_check_count = 4194304 # 每次检查的最大进程数

调试建议

  1. Soft Lockup:

    • 查看 RIP(指令指针)定位死循环位置
    • 检查是否禁用抢占过久或算法复杂度问题
  2. Hard Lockup:

    • 必须依赖 NMI,确保 BIOS 未禁用 perf/NMI
    • 通常是 spin_lock_irq 滥用或中断 handler 问题
    • 若看到 RIP: _raw_spin_lock_irq+... 说明关中断锁导致
  3. Hung Task:

    • 查看 Call Trace 中的 wait_for_completion 或 schedule_timeout
    • 通常是块设备、网络存储或自定义驱动的问题
    • 可尝试 echo > /sys/block/sda/device/delete 强制删除设备(可能恢复)

严重程度:Hard Lockup > Soft Lockup > Hung Task,但 Hung Task 最隐蔽(系统看似正常)。

posted @ 2026-02-25 17:18  uran0sh  阅读(140)  评论(0)    收藏  举报