- 由 b178903294创建, 最后修改于9月 23, 2019
严格意义来讲nmi_watchdog ,属于中断检测范畴,是基于非屏蔽中断NMI的检测机制,是一种内核状态监护的狗,关于其介绍可参考nmi_watchdog.txt
|
|
简而言之就是NMI要基于APIC,还要考虑硬件平台的中断架构,由于我们seewobook SN21采用的是intel N3350所以中断架构就是SMP,所以我们的nmi_watchdog=1,也就是I/O APIC watchdog。其缺点很明显:每个时钟周期都要触发NMI,这对性能是个不小的影响,引用上面的原话 "...its NMI frequency is much higher, resulting in a more significant hit to the overall system performance",cpu性能大概消耗近1%,这对于一个监护程序来说很夸张了。而且可靠性不太好。
关于死锁检测原理可参照:https://blog.csdn.net/zhouhuacai/article/details/78046077
1.先来看看softlockup相关的原理和测试:
SoftLockup 检测首先需要对每一个CPU core注册叫做watchdog的kernel线程。即[watchdog/0],[watchdog/1],[watchdog/2]…
同时,系统会有一个高精度的计时器hrtimer(一般来源于APIC),该计时器能定期产生时钟中断,该中断对应的中断处理例程是kernel/watchdog.c: watchdog_timer_fn(),在该例程中:
- 要递增计数器hrtimer_interrupts,这个计数器同时为hard lockup detector用于判断CPU是否响应中断;
- 还要唤醒[watchdog/x]内核线程,该线程的任务是更新一个时间戳;
- soft lock detector检查时间戳,如果超过soft lockup threshold一直未更新,说明[watchdog/x]未得到运行机会,意味着CPU被霸占,也就是发生了soft lockup。
注意,这里面的内核线程[watchdog/x]的目的是更新时间戳,该时间戳是被watch的对象。而真正的看门狗,则是由时钟中断触发的 watchdog_timer_fn(),这里面 [watchdog/x]是被scheduler调用执行的,而watchdog_timer_fn()则是被中断触发的。
下面贴出nmi_watchdog 检测softlockup触发panic的主逻辑代码:
kernel/watchdog.c
|
|
上述代码通过if (touch_ts == 0) 判断是否返回退出,没发生softlockup的时候,touch_ts全都为负或0,所以其int值均为0,总是返回退出,当touch_ts如同log里面大于0时,就要跳过if语句开始执行后面的代码了。通过这两句duration = is_softlockup(touch_ts); if (unlikely(duration)) 来判断softlockup超时时间,大于零就开始执行panic流程。打印一条pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", smp_processor_id(), duration, current->comm, task_pid_nr(current));接着panic打印一条panic("softlockup: hung tasks"); 这与下面我们测试看到的log信息一致,如果panic没有死的话我们的系统就会重启了,并保存相关log到/var/spool/crash/下,开机第一件事情就是把这个目录下的log全部保存,因为过一会儿系统会删除掉,这些log对于定位死锁内核程序很有帮助。
我们在kernel/kernel目录下编译个内核模块,启动系统后装载进内核来测试nmi_watchdog的功能。代码如下:
kernel/softlockup.c
|
|
上述代码是从网上找到的,它通过spinlock()实现关抢占,使得该CPU上的[watchdog/x]无法被调度。另外,通过set_cpus_allowed_ptr()将该线程绑定到特定的CPU上去。
别忘了在kernel/Makefile文件中加入一行:obj-m +=softlockup.o 我们不直接装载到内核中,因为这样系统会有几率从开机开始一直重复触发softlockup,不是卡死就是循环重启,我们没办法看log。
编译完成后我们直接把新编译的kernel部署到seewobook上。开机后insmod /lib/module/4.4.159/kernel/kernel/softlockup.ko 就开始测试了。
经过测试,发现进行softlockup后,nmi_watchdog有几率会重启,说明确实稳定行不行。nmi_watchdog成功检测softlockup并触发panic相关log如下:
展开源码
2.hardlockup原理和测试
nmi_watchdog最主要的功能是检测hardlockup,这个才是他的主业。检测hard lockup的原理利用了PMU的NMI perf event,因为NMI中断是不可屏蔽的,在CPU不再响应中断的情况下仍然可以得到执行,它再去检查时钟中断的计数器hrtimer_interrupts是否在保持递增,如果停滞就意味着时钟中断未得到响应,也就是发生了hard lockup。
代码实现原理就是读取现在的hrtimer_interrupts和之前存储的数值进行比较,如果两个值一样,那么说明中断被阻塞了即发生了hardlockup,那么就要开始触发panic了。代码如下:
|
|
控制触发panic逻辑代码如下:
|
|
hardlockup测试代码:
hardlockup.c
|
|
在上述实例中,中断被关闭,普通中断无法被相应(包括时钟中断),线程无法被调度,因此,在这种情况下,不仅仅[watchdog/x]线程也无法工作,hrtimer也无法被相应。编译和安装操作参考上面softlockup测试。
触发hardlockup重启后的crash log如下:
折叠源码
|
|
至此,nmi_watchdog相关的softlockup和hardlockup均已测试完毕,可见功能是正常的,只是稳定性可能差了一点。nmi_watchdog主要用于内核代码的检测和重置,主要在内核大神们开发阶段使用,一般是不建议在用户机中使用的,因为其不大稳定并且性能开销有点大,所以表现不大好。对于我们更常见的用户态hang的检测一般是交给softdog和iTCO_wdt的,softdog是完全基于软件的狗,所以也可能会随着系统崩溃而死掉,iTCO_wdt是基于硬件的 ,可靠性显然比前两个都高,但是由于SN21硬件配置错误导致iTCO_wdt已废,所以咱们目前只有指望这两个表现不大稳定的狗了,当这两个狗不起作用的时候还是老老实实F3+power手动重启吧。
本文介绍了NMI_Watchdog的功能和原理,涉及软lockup和硬lockup的检测机制。通过测试展示了如何触发softlockup和hardlockup,并分析了相关 Panic 日志,讨论了其在内核开发和用户态hang检测中的应用与局限性。

116

被折叠的 条评论
为什么被折叠?



