目录
系统(在一个或多个CPU核上)保持在长时间无反应状态。可检测类型有watchdog、soft lockup、hard lockup、 hung task、workqueue stall 等。
检测系统的健康状态,有能力重启系统。
CONFIG_SOFT_ WATCHDOG=m

查看内核中看门狗的运行
- #ps -e | grep watch
- 103 ? 00:00:00 watchdogd
Kernel hacking | Debug Oops, Lockups and Hangs

看门狗的配置
- # sysctl -a | grep watchdog
- //0:关闭NMI看门狗和硬件lockup检测
- kernel.nmi_watchdog = 0
- //开启软件lockup检测
- kernel.soft_watchdog = 1
- //1 开启两者(软/硬)
- kernel.watchdog = 1
- //
- kernel.watchdog_cpumask = 0-127
- //硬件lockup 超时,软件lockup 2*10
- kernel.watchdog_thresh = 10
内核处于紧密的循环中,长时间不让其他任务得到调度
当检测到软锁定时
测试程序 :自旋spin_(un)lock()
- kernel_thread 线程中有如下循环,CPU密集型
-
- spin_lock(&spinlock);
- while (i < 10000000000) {
- i ++;
- if (!(i%50000000))
- PRINT_CTX();
- }
-
- spin_unlock(&spinlock);
检测输出
- [ 312.261567] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [lkd/kt_stuck:589]
-
- [ 354.256680] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:589 | .N.0 /* simple_kthread() */
- [ 354.722453] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:589 | .N.0 /* simple_kthread() */
在内核模式下运行的CPU内核仍处于紧密循环状态,不允许其他硬件中断运行;
系统检测到硬锁时
内核配置
1、硬锁定只能由NMI,在本机x86_64上检测到;
2、必须启用NMI和NMI看门狗 nmi_ watchdog=1
3、CONFIG_RCU_CPU_STALL_TIMEOUT 值的范围 (3~300)在此时间内一定能检测到
4、CONFIG_RCU_STALL_COMMON=y
测试程序 自旋转IRQs、禁止抢占 spin_(un)lock_irq()
- kernel_thread 线程中有如下循环,CPU密集型
-
- spin_lock_irq(&spinlock);
- while (i < 10000000000) {
- i ++;
- if (!(i%50000000))
- PRINT_CTX();
- }
-
- spin_unlock_irq(&spinlock);
检测输出
- [ 4557.452812] rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
- [ 4557.454426] rcu: 1-...0: (1 ticks this GP) idle=43e/1/0x4000000000000000 softirq=6242/6242 fqs=2599
- [ 4557.455684] rcu: (detected by 2, t=5252 jiffies, g=13033, q=119)
- [ 4557.457412] Task dump for CPU 1:
- [ 4557.458131] lkd/kt_stuck R running task 0 793 2 0x0000002a
- [ 4557.459379] Call trace:
- [ 4557.460526] __switch_to+0xd0c/0xd44
- [ 4557.461157] logbuf_lock+0x0/0x4
- [ 4557.464316] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:793 | dN.0 /* simple_kthread() */
内核设置
Kernel hacking | Debug Oops, Lockups and Hangs | Detect Hung Tasks
配置见图二
参数解析
- # sudo sysctl -a|grep hung_task
- //如果设置1 则内核给所有核发送NMI中断,触发堆栈追溯
- kernel.hung_task_all_cpu_backtrace = 0
- //检测任务数的上线
- kernel.hung_task_check_count = 4194304
- //0 意味着挂起任务的值是kernel.hung_task_timeout_secs
- kernel.hung_task_check_interval_secs = 0
- //1:kernel panix 0:任务维持挂起状态
- kernel.hung_task_panic = 0
- //设置0 则禁止检测
- kernel.hung_task_timeout_secs = 120
- //报告的最大经过数
- kernel.hung_task_warnings = 10
内核设置
Kernel hacking | Debug Oops, Lockups and Hangs | Detect Workqueue Stalls
配置见图二
参数解析
检测时间workqueue.watchdog_thresh 默认30秒,设置0 禁止检测
测试例子:在workqueue回调函数中,添加CPU密集型函数
- static void work_func(struct work_struct *work)
- {
- struct st_ctx *priv = container_of(work, struct st_ctx, work);
- u64 i = 0;
- PRINT_CTX();
- //CPU密集型执行
- while (1)
- i += 3;
- }
-
- static int __init workq_simple_init(void)
- {
- ctx.data = INITIAL_VALUE;
- //初始化workqueue
- INIT_WORK(&ctx.work, work_func);
- return 0;
- }
测试输出
- [ 580.742603] BUG: workqueue lockup - pool cpus=1 node=0 flags=0x0 nice=0 stuck for 73s!
- [ 529.474102] rcu: INFO: rcu_sched self-detected stall on CPU
- [ 529.474499] rcu: 1-....: (20464 ticks this GP) idle=fc6/1/0x4000000000000002 softirq=4407/4408 fqs=9074