请记住内核中这个勤劳的监测卫士---Watchdog(Hard lockup篇)

本文详细解读了Linux内核中Hardlockup的检测原理,涉及watchdog_timer_fn函数、hardlockup检测函数以及内核配置。通过实例分析,探讨了死锁与Hardlockup的关系,并提供了解决思路。适合深入理解内核调度与中断响应的开发者阅读。
摘要由CSDN通过智能技术生成

​更多内核安全、eBPF分析和实践文章,请关注博客和公众号:

CSDN博客:内核功守道
公众号: 内核功守道

背景

接上篇文章:请记住内核中这个勤劳的监测卫士—Watchdog(Soft lockup篇),本篇详细分析Hard lockup流程和原理,并给出此类问题分析经验,供大家参考。

我们知道,hardware watchdog是Soc内的一个内部外设,是一个硬件模块,常说的watchdog driver指的就是该硬件。Hard lockup比soft lockup更加严重,CPU不仅无法调度其它进程,而且不能响应中断。在开启soft lockup时,已经给每个CPU启动了一个hrtimer定时器,在定时器中断处理函数watchdog_timer_fn中更新hrtimer_interrupts变量。

检测hard lockup的原理是:

  • 在CPU0的watchdog_timer_fn函数中检测CPU1的hrtimer_interrupts变量是否更新过;
  • 若没更新,意味着CPU1不能响应中断,出现了hard lockup(CPU1检测CPU2、CPU2检测CPU3、CPU3检测CPU0);
  • 在驱动中加入以下代码可触发hard lockup
static spinlock_t spinlock;
unsigned long flags;
spin_lock_init(&spinlock);

spin_lock_irqsave(&spinlock, flags);
while (1);
  • 在上述代码中,本地抢占和本地中断被关闭,该CPU的普通中断无法被响应(包括hrtimer定时器中断),线程也无法调度。在这种情况下,[watchdog/x]线程无法工作,hrtimer中断也无法被响应,就会出现hard lockup。

Hard lockup源码分析

1、hrtimer中断处理函数

watchdog_timer_fn()
{
/* hrtimer_interrupts++ */
	watchdog_interrupt_count();
	/* test for hardlockups on the next cpu */
	watchdog_check_hardlockup_other_cpu();
}

2、Hard lockup检测函数

void watchdog_check_hardlockup_other_cpu(void)
{
	unsigned int next_cpu;

	/* hrtimer的中断4s触发一次,“%3”表示经过3个周期*,即每隔12s检测一下是否 */
	/* hard lockup*/
	if (__this_cpu_read(hrtimer_interrupts) % 3 != 0)
		return;
		/* 得到下一颗CPU */
	next_cpu = watchdog_next_cpu(smp_processor_id());
	if (is_hardlockup_other_cpu(next_cpu)) {
		if (hardlockup_panic)//是否panic
			panic("Watchdog detected hard LOCKUP on cpu %u", next_cpu);
		else
			WARN(1, "Watchdog detected hard LOCKUP on cpu %u", next_cpu);
       per_cpu(hard_watchdog_warn, next_cpu) = true;
	} else {
		per_cpu(hard_watchdog_warn, next_cpu) = false;
	}
}

3、Hard lockup判断函数

static int is_hardlockup_other_cpu(unsigned int cpu)
{
	unsigned long hrint = per_cpu(hrtimer_interrupts, cpu);
	/* 如果相等,说明hrtimer中断函数没有执行,出现hard lockup */
	if (per_cpu(hrtimer_interrupts_saved, cpu) == hrint)
		return 1;
	/* 保存最新的hrtimer_interrupts变量值 */
	per_cpu(hrtimer_interrupts_saved, cpu) = hrint;
	return 0;
}

内核配置

  • 开启hard lockup(默认为y)
HARDLOCKUP_DETECTOR_OTHER_CPU
  • 是否需要panic(默认为n)
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC
  • 在应用层做以下设置也可以触发:
echo 1 > /proc/sys/kernel/hardlockup_panic

问题分析思路

Soft lockup用于检测CPU调度是否正常,而Hard lockup主要用于检测CPU中断响应是否正常。内核调度以及中断响应的正常与否,和死锁有很深入的关系,也可以是说是检测系统死锁的一种机制。

  • 某个中断服务函数长时间运行;
  • 关中断时间过长,譬如使用spin_lock_irqsave()函数关闭中断之后,太久没释放;

遇到此类问题,最有效的方法就是使用Trace32或者ARM DS5这类的在线调试器,查看出现异常卡死的位置或者哪个模块最近一次关了中断没有释放,进一步分析可疑点。

总结

以上两篇详细分析了Soft lockup和Hard lockup流程,并介绍了问题解决思路。可以看到不管是Soft lockup还是Hard lockup,都是从内核态的角度来分析死锁的情况,这也是很多内核工程师经常会遇到的问题。

尽管内核watchdog能检测softlockup 和 hardlockup 并采取相应的措施,但并非所有的系统宕机都是因为内核线程lockup引起的。用户线程/进程一样有可能引发系统宕机的情况。比如,用户程序有可能占着临界资源无法释放或系统太忙(疲于响应各种中断),导致无法调度其他用户进程(此时watchdog内核线程不受影响),这也可能导致系统无法正常使用。

后续会详细分析Android场景下的用户态Watchdog以及具体案例,敬请期待。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芯光未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值