51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 3656|回复: 2
打印 上一主题 下一主题

[转贴] linux内核线程死锁或死循环(soft lockup)之后如何让系统宕机重启

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-11-20 13:37:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在开发内核模块或驱动时,如果处理失误,导致内核线程中出现死锁或者死循环,你会发现,除了重启之外,你没有任何可以做的。这时你的输入不起任何作用,终端(不是指远程的ssh工具)只会在那重复的输出类似“BUG: soft lockup - CPU#0 stuck for 67s! [fclustertool:2043]”,更无奈的是你重启之后导致系统挂起的堆栈信息也看不到,你所能做的就是一遍遍的加调试信息,一遍遍的重启机器(这是我的经历,现在想想很傻)。
  这种情况你肯定不是第一个遇到的,所以内核肯定会提供处理这种情况的一些机制。但是如何来找到这些机制在哪个地方,或者说根据什么信息去google呢?最有用的就是这句话“BUG: soft lockup - CPU#0 stuck for 67s! [fclustertool:2043]”,因为这句话提供你的信息量很大。首先,这条信息可以输出,说明即使发生死锁或者死循环,还是有代码可以执行。第二,可以通过这个日志信息,找到对应的处理函数,这个函数所在的模块就是用来处理CPU被过度使用时用到的。所以通过这个事情,可以看到内核打印出的只言片语都有可能成为你解决问题的关键,一定要从重视这些信息,从中找出有用的东西。
  我经常看的内核版本是官方的2.6.32内核,这个版本中我找到的函数是softlockup_tick(),这个函数在时钟中断的处理函数run_local_timers()中调用。这个函数会首先检查watchdog线程是否被挂起,如果不是watchdog线程,会检查当前占有CPU的线程占有的时间是否超过系统配置的阈值,即softlockup_thresh。如果当前占有CPU的时间过长,则会在系统日志中输出我们上面看到的那条日志。接下来才是最关键的,就是输出模块信息、寄存器信息和堆栈信息,检查softlockup_panic的值是否为1。如果softlockup_panic为1,则调用panic()让内核挂起,输出OOPS信息。代码如下所示:





  • /*
  • * This callback runs from the timer interrupt, and checks
  • * whether the watchdog thread has hung or not:
  • */  
  • void softlockup_tick(void)  
  • {  
  •     int this_cpu = smp_processor_id();  
  •     unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu);  
  •     unsigned long print_timestamp;  
  •     struct pt_regs *regs = get_irq_regs();  
  •     unsigned long now;  
  •     ......  
  •   
  •     /* Warn about unreasonable delays: */  
  •     if (now <= (touch_timestamp + softlockup_thresh))  
  •         return;  
  •   
  •     per_cpu(print_timestamp, this_cpu) = touch_timestamp;  
  •     spin_lock(&print_lock);  
  •     printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n",  
  •             this_cpu, now - touch_timestamp,  
  •             current->comm, task_pid_nr(current));  
  •     print_modules();  
  •     print_irqtrace_events(current);  
  •     if (regs)  
  •         show_regs(regs);  
  •     else  
  •         dump_stack();  
  •     spin_unlock(&print_lock);  
  •   
  •   
  •     if (softlockup_panic)  
  •         panic("softlockup: hung tasks");  
  • }  

  但是softlockup_panic的值默认竟然是0,所以在出现死锁或者死循环的时候,会一直只输出日志信息,而不会宕机,这个真是好坑啊!所以你得手动修改/proc/sys/kernel/softlockup_panic的值,让内核可以在死锁或者死循环的时候可以宕机。如果你的机器中安装了kdump,在重启之后,你会得到一份内核的core文件,这时从core文件中查找问题就方便很多了,而且再也不用手动重启机器了。如果你的内核是标准内核的话,可以通过修改/proc/sys/kernel/softlockup_thresh来修改超时的阈值,如果是CentOS内核的话,对应的文件是/proc/sys/kernel/watchdog_thresh。CentOS内核和标准内核还有一个地方不一样,就是处理CPU占用时间过长的函数,CentOS下是watchdog_timer_fn()函数。
  这里介绍下lockup的概念。lockup分为soft lockup和hard lockup。 soft lockup是指内核中有BUG导致在内核模式下一直循环的时间超过10s(根据实现和配置有所不同),而其他进程得不到运行的机会。hard softlockup是指内核已经挂起,可以通过watchdog这样的机制来获取详细信息。这两个概念比较类似。
  注意上面说的这些,都是在内核线程中有效,对用户态的死循环没用。如果要监视用户态的死循环,或者内存不足等资源的情况,强烈推荐软件层面的watchdog。你可以自己开发基于soft watchdog的监控程序,也可以安装watchdog包通过修改配置来做,非常的方便。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-22 20:46 , Processed in 0.072028 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表