热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

softlockup检测(watchdog)原理(用于检测系统调度是否正常)

softlockup(watchdog)用于检测系统调度是否正常,即软锁的情况,当发生softlockup时,内核不能调度,

softlockup(watchdog)用于检测系统调度是否正常,即软锁的情况,当发生softlockup时,内核不能调度,但还能响应中断,对用户的表现可能为:能ping通,但无法登陆系统,无法进行正常操作。
其基本原理为:为每个CPU启动一个内核线程(watchdog/x),此线程为优先级最高的实时线程,在该线程得到调度时,会更新相应的计数(时间戳),同时会启动定时器,当定时器到期时检查相应的时间戳,如果超过指定时间,都没有更新,则说明这段时间内都没有发生调度(因为此线程优先级最高),则打印相应告警或根据配置可以进入panic流程。
基本代码分析(2.6.32)
rest_init->kernel_init->lockup_detector_init->cpu_callback->watchdog_prepare_cpu(初始化watchdog定时器):

点击(此处)折叠或打开

  1. static int watchdog_prepare_cpu(int cpu)

  2. {

  3.     struct hrtimer *hrtimer = &per_cpu(watchdog_hrtimer, cpu);


  4.     WARN_ON(per_cpu(softlockup_watchdog, cpu));

  5.     hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);//初始化高精度定时器

  6.     hrtimer->function = watchdog_timer_fn;//设置定时器处理函数


  7.     return 0;

  8. }

看门狗定时器处理函数:

点击(此处)折叠或打开

  1. static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)

  2. {

  3. //获取计数watchdog_touch_ts,该计数在watchdog内核线程被调度时更新

  4.     unsigned long touch_ts = __get_cpu_var(watchdog_touch_ts);

  5.     struct pt_regs *regs = get_irq_regs();

  6.     int duration;


  7.     /* kick the hardlockup detector */

  8. //增加中断计数,证明没有发生硬锁(关中断死锁)

  9.     watchdog_interrupt_count();


  10.     /* kick the softlockup detector */

  11. //唤醒wathdog内核线程

  12.     wake_up_process(__get_cpu_var(softlockup_watchdog));


  13.     /* .. and repeat */

  14. //重启定时器

  15.     hrtimer_forward_now(hrtimer, ns_to_ktime(get_sample_period()));

  16.     if (touch_ts == 0) {

  17.         if (unlikely(__get_cpu_var(softlockup_touch_sync))) {

  18.             /*

  19.              * If the time stamp was touched atomically

  20.              * make sure the scheduler tick is up to date.

  21.              */

  22.             __get_cpu_var(softlockup_touch_sync) = false;

  23.             sched_clock_tick();

  24.         }

  25.         __touch_watchdog();

  26.         return HRTIMER_RESTART;

  27.     }


  28.     /* check for a softlockup

  29.      * This is done by making sure a high priority task is

  30.      * being scheduled. The task touches the watchdog to

  31.      * indicate it is getting cpu time. If it hasn'then

  32.      * this is a good indication some task is hogging the cpu

  33.      */

  34. //判断是否发生了软锁,原理是判断touch_ts(时间戳)是否超过一定时间没有更新

  35.     duration = is_softlockup(touch_ts);

  36.     if (unlikely(duration)) {

  37.         /* only warn once */

  38.         if (__get_cpu_var(soft_watchdog_warn) == true)

  39.             return HRTIMER_RESTART;

  40. //发生了软锁后,进行一些列的信息记录和告警。

  41.         printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",

  42.             smp_processor_id(), duration,

  43.             current->comm, task_pid_nr(current));

  44.         print_modules();

  45.         print_irqtrace_events(current);

  46.         if (regs)

  47.             show_regs(regs);

  48.         else

  49.             dump_stack();

  50. //如果配置了softlockup_panic(proc中配置),则panic

  51.         if (softlockup_panic)

  52.             panic("softlockup: hung tasks");

  53.         __get_cpu_var(soft_watchdog_warn) = true;

  54.     } else

  55.         __get_cpu_var(soft_watchdog_warn) = false;


  56.     return HRTIMER_RESTART;

  57. }


启动看门狗,即创建watchdog内核线程。

点击(此处)折叠或打开

  1. static int watchdog_enable(int cpu)

  2. {

  3.     struct task_struct *= per_cpu(softlockup_watchdog, cpu);

  4.     int err = 0;


  5.     /* enable the perf event */

  6.     err = watchdog_nmi_enable(cpu);


  7.     /* Regardless of err above, fall through and start softlockup */


  8.     /* create the watchdog thread */

  9.     if (!p) {

  10. //创建watchdog内核线程

  11.         p = kthread_create(watchdog, (void *)(unsigned long)cpu, "watchdog/%d", cpu);

  12.         if (IS_ERR(p)) {

  13.             printk(KERN_ERR "softlockup watchdog for %i failed\n", cpu);

  14.             if (!err)

  15.                 /* if hardlockup hasn't already set this */

  16.                 err = PTR_ERR(p);

  17.             goto out;

  18.         }

  19.         kthread_bind(p, cpu);

  20.         per_cpu(watchdog_touch_ts, cpu) = 0;

  21.         per_cpu(softlockup_watchdog, cpu) = p;

  22.         wake_up_process(p);

  23.     }


  24. out:

  25.     return err;

  26. }


watchdog内核线程执行主函数,主要是要更新计数(时间戳)

点击(此处)折叠或打开

  1. static int watchdog(void *unused)

  2. {

  3. //设置为最高优先级

  4.     struct sched_param param = { .sched_priority = MAX_RT_PRIO-};

  5.     struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);

  6. //设置为实时线程

  7.     sched_setscheduler(current, SCHED_FIFO, &param);


  8.     /* initialize timestamp */

  9. //初始化计数(时间戳)

  10.     __touch_watchdog();


  11.     /* kick off the timer for the hardlockup detector */

  12.     /* done here because hrtimer_start can only pin to smp_processor_id() */

  13. //启动定时器,用于检测是否发生软锁

  14.     hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()),

  15.          HRTIMER_MODE_REL_PINNED);

  16. //睡眠

  17.     set_current_state(TASK_INTERRUPTIBLE);

  18.     /*

  19.      * Run briefly once per second to reset the softlockup timestamp.

  20.      * If this gets delayed for more than 60 seconds then the

  21.      * debug-printout triggers in watchdog_timer_fn().

  22.      */

  23.     while (!kthread_should_stop()) {

  24. //更新计数

  25.         __touch_watchdog();

  26.         schedule();


  27.         if (kthread_should_stop())

  28.             break;


  29.         set_current_state(TASK_INTERRUPTIBLE);

  30.     }

  31.     __set_current_state(TASK_RUNNING);


  32.     return 0;

  33. }


判断是否发生软锁:is_softlockup

点击(此处)折叠或打开

  1. static int is_softlockup(unsigned long touch_ts)

  2. {

  3.     unsigned long now = get_timestamp(smp_processor_id());


  4.     /* Warn about unreasonable delays: */

  5. //检测计数多久没有更新了,如果超过了60s,则表示发生了软锁

  6.     if (time_after(now, touch_ts + softlockup_thresh))

  7.         return now - touch_ts;


  8.     return 0;

  9. }


本文转自 guowang327 51CTO博客,原文链接:http://blog.51cto.com/guowang327/1962741,如需转载请自行联系原作者


推荐阅读
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 【MySQL】frm文件解析
    官网说明:http:dev.mysql.comdocinternalsenfrm-file-format.htmlfrm是MySQL表结构定义文件,通常frm文件是不会损坏的,但是如果 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • 尽管在WPF中工作了一段时间,但在菜单控件的样式设置上遇到了一些基础问题,特别是关于如何正确配置前景色和背景色。 ... [详细]
  • 在测试软件或进行系统维护时,有时会遇到电脑蓝屏的情况,即便使用了沙盒环境也无法完全避免。本文将详细介绍常见的蓝屏错误代码及其解决方案,帮助用户快速定位并解决问题。 ... [详细]
  • 本文深入探讨了Go语言中的接口型函数,通过实例分析其灵活性和强大功能,帮助开发者更好地理解和运用这一特性。 ... [详细]
  • 入门指南:使用FastRPC技术连接Qualcomm Hexagon DSP
    本文旨在为初学者提供关于如何使用FastRPC技术连接Qualcomm Hexagon DSP的基础知识。FastRPC技术允许开发者在本地客户端实现远程调用,从而简化Hexagon DSP的开发和调试过程。 ... [详细]
  • 使用OpenGL实现三维空间中任意两点间圆柱体管道的绘制
    本文介绍了如何利用OpenGL在三维空间中的任意两个点之间绘制具有指定半径的圆柱体管道。鉴于OpenGL较为底层,许多功能需自行实现,文中提供了详细的代码示例及解析。 ... [详细]
  • 本文分享了作者在使用LaTeX过程中的几点心得,涵盖了从文档编辑、代码高亮、图形绘制到3D模型展示等多个方面的内容。适合希望深入了解LaTeX高级功能的用户。 ... [详细]
  • 本文详细介绍了 Node.js 中 OS 模块的 arch 方法,包括其功能、语法、参数以及返回值,并提供了具体的使用示例。 ... [详细]
  • 利用Node.js实现PSD文件的高效切图
    本文介绍了如何通过Node.js及其psd2json模块,快速实现PSD文件的自动化切图过程,以适应项目中频繁的界面更新需求。此方法不仅提高了工作效率,还简化了从设计稿到实际应用的转换流程。 ... [详细]
  • 深入解析C语言中的关键字及其分类
    本文将全面介绍C语言中的关键字,并按照功能将其分为数据类型关键字、控制结构关键字、存储类别关键字和其他关键字四大类,旨在帮助读者更好地理解和运用这些基本元素。C语言中共有32个关键字。 ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • 本文探讨了如何将个人经历,特别是非传统的职业路径,转化为职业生涯中的优势。通过作者的亲身经历,展示了舞蹈生涯对商业思维的影响。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
author-avatar
哇哈时候_206
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有