linux内核中softlockup,hardlockup代码实现

2024-10-02 13:03:51 浏览数 (2)

一,softlockup: watchdog软狗/软锁----用于检测系统调度是否正常。 能响应中断,但调度异常。

软件死锁:内核在内核模式下循环超过20s (watchdog_thresh*2),没有给其它进程机会去运行。

默认系统保持死锁显示当前堆栈信息。可以通过softlockup_panic=1来配置主动panic系统。

运行时参数sysctl:

1, /proc/sys/kernel/watchdog -->watchdog_enable //默认为1,使能,开启watchdog

2, /proc/sys/kernel/watchdog_thresh -->watchdog_thresh //默认为10s,但watchdog的定时器检查时间是: watchdog_thresh*2/5

3, /proc/sys/kernel/softlockup_panic -->softlockup_panic //默认为0, 即默认只是显示告警堆栈, 为1表示会panic系统。

4, /proc/sys/kernel/nmi_watchdog -->watchdog_enabled // 0(关闭hardlockup,softlockup); panic,nopanic

:~ # sysctl -a | grep watchdog

kernel.watchdog = 1

kernel.watchdog_thresh = 10

kernel.nmi_watchdog = 1

:~ # sysctl -a | grep softlockup

kernel.softlockup_panic = 0

softlockup与hardlockup的启动参数:

1>,softlockup_panic=1 在检测到softlockup时panic系统, 如果为0,watchdog也会检测softlockup但不会panic.

2>,nosoftlockup/nowatchdog : watchdog_enable=0,即关闭softlockup也会关闭hardlockup,即关闭软狗与硬狗.

启动参数:

3>,nmi_watchdog=[panic,] [nopanic,] [num] ----> hardlockup_panic_setup( )

设置非屏蔽中断(NMI)watchdog的特性。"0"表示禁用NMI watchdog(也会关闭softlockup);

panic: 表示在hardlockup发生时,主动panic系统。nopanic:只打印告警信息。

运行时关闭与开启:

echo 0 >/proc/sys/kernel/nmi_watchdog 运行时关闭硬锁检测。

echo 1> /proc/sys/kernel/nmi_watchdog 运行时重新使能硬锁检测。

4>,nowatchdog: watchdog_enable=0,关闭softlockup 和hardlockup,即关闭软狗与硬狗.

softlockup原理图:

初始化流程:

init/main.c

start_kernel()

rest_init()

-->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); //创建1号进程,它最后会执行用户态的init进程

kernel_init()--> //1号进程

lockup_detector_init(); //watchdog初始化,开启第一个watchdog/%d

cpu_callback(&cpu_nfb,CPU_UP_PREPARE,cpu)

register_cpu_notifier(&cpu_nfb); //把通知块cpu_nfb(回调函数为cpu_callback)加入到通知链cpu_chain

smp_init(); //唤起其它CPU,开启其它watchdog/%d

cpu_up(cpu)

->_cpu_up(cpu, 0);

->__cpu_notify

->notifier_call_chain() //遍历cpu_chain,并执行cpu_nfb通知块对应的函数cpu_callback

kernel/watchdog.c

static int __cpuinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)

{

int hotcpu = (unsigned long)hcpu;

switch (action) {

case CPU_UP_PREPARE:

case CPU_UP_PREPARE_FROZEN:

watchdog_prepare_cpu(hotcpu); //初始化定时器watchdog_hrtimer

break;

case CPU_ONLINE:

case CPU_ONLINE_FROZEN:

if (watchdog_enabled)

watchdog_enable(hotcpu); //创建"watchdog/%d"内核线程,也会调用watchdog_nmi_enable(cpu)使能hardlockup

break;

...

}

二,hardlockup: nmi_watchdog硬狗/硬锁----用于检测中断系统是否正常。

硬件死锁:CPU在内核模式下循环超过10s(watchdog_thresh)没有给其它中断机会运行则默认系统保持死锁。可以通过nmi_watchdog=panic配置当检查到hardlockup时主动panic系统.

在当前X86/X86_64的通用平台上,有一个硬件特性:能产生 watchdog NMI interrupts. 即产生:不可屏蔽中断。

通过周期性的执行NMI中断,可以监视每个CPU是否被锁死。

hardlockup: 硬锁实现原理 (当前用PMU实现, Performance monitor units性能管理监视单元)

为了使能NMI watchdog, 内核需要支持APIC。

X86 SMP系统内核:APIC已自动编译进内核。

X86 UP系统内核:需启用CONFIG_X86_UP_APIC(Processor type and features -> Local APIC support on uniprocessors)

或CONFIG_X86_UP_IOAPIC(Processor type and features -> IO-APIC support on uniprocessors)。

注:CONFIG_X86_UP_APIC用于没有IO-APIC的单处理器机器。

CONFIG_X86_UP_IOAPIC用于具有IO-APIC的单处理器。

对于X86_64, APIC也已自动编译进内核。

NMI watchdog中断:

当使用 Local-APIC时,NMI interrupts 频率取决于系统load负载。

因为Local-APIC NMI watchdog没有更好的"中断源". 使用的是"cycles unhalted"事件。当系统idle,CPU在halted状态时不会产生tick事件.

如果系统硬死锁在除了"hlt"指令的任何地方,硬狗watchdog会在每个时钟周期clock tick中因"cycles unhalted"事件很快触发。

但是如果系统硬死锁在了"hlt"指令内, 则"cycles unhalted"事情就不会被触发,即不会触发watchdog.

--这就是Local-APIC watchdog的缺点。不幸的是:没有"clock ticks"事性可以始终工作。

使用 IO-APIC NMI watchdog 没有这个缺点。但是因为它是由外部设备驱动的, 由于它的中断频率比较高,对整个系统的性能有比较大的影响。

硬锁死锁的判断:

如果系统中的任何一个CPU没有执行"周期性的时钟中断"超过10s, 那么NMI处理程序就会产生一个oops并杀死进程.

初始化流程:

kernel/watchdog.c

watchdog_enable(cpu)

-->watchdog_nmi_enable(cpu);

wd_attr = &wd_hw_attr;

wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh); // cpu_khz*1000*watchdog_thresh

perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);

PMU说明:翻译 tools/perf/design.txt

linux性能计数器:Performance Counters for Linux

------------------------------

性能计数器(Performance counters)是一类多数现代CPU中都有的特殊硬件寄存器。

这些寄存器计录了一些特定的硬件事件hw events: (不会减慢内核或应用程序)

如:

执行的指令数,instructions executed.

缓存未命中的损失,cachemisses suffered.

分支预测错误,branches mis-predicted.

这些寄存器也可以用来触发中断:比如设置一个事情的阈值,当此事性的阈值到时,就可以产生中断。

因此可以用(寄存器产生的中断)来分析在该CPU上运行的代码。

性能监视:可以参考使用命令perf

源码注释:kernel/watchdog.c

0 人点赞