Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1241284
  • 博文数量: 122
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4004
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-20 08:27
文章分类
文章存档

2016年(1)

2015年(21)

2014年(100)

分类: LINUX

2014-04-18 14:20:39

nmi_watchdog原理(用于检测关中断死锁)
nmi_watchdog用于检测内核中关中断死锁(也称硬死锁)的情况,是调测内核死机或死锁问题的一大利器。内核中,如果代码编写不好可能会出现关中断死锁的情况,即进入内核态后,关中断,然后在内核态中死锁,或长时间运行,导致该CPU无法响应中断(因为中断已关),也无法得到调度(对于没有启用内核抢占的内核来说),外在表现可能为系统挂死、无法ping通、没有响应。而nmi_watchdog正是针对这种情况而设计的。
其基本原理为:注册nmi中断(3号中断),为不可屏蔽中断,由硬件定期触发(通过性能计数器)。在时钟中断中更新相关计数器,在nmi中断处理中,判断相关计数器是否更新,如果超过5s(默认情况下)没有更新,则触发nmi_watchdog,默认情况下,最终会进入panic流程。
2.6.11代码流程如下:
本地时钟中断处理函数:


点击(此处)折叠或打开

  1. fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
  2. {
  3.  /**
  4.   * 获得CPU逻辑号
  5.   */
  6.  int cpu = smp_processor_id();

  7.  /*
  8.   * the NMI deadlock-detector uses this.
  9.   */
  10.  /*增加apic_timer_irqs计数,此计数用于nmi_watchdog,其会在do_nmi中检测这个值的更新状态 */
  11.  irq_stat[cpu].apic_timer_irqs++;
  12. ...
  13. }
nmi中断的处理函数:do_nmi->default_do_nmi()

点击(此处)折叠或打开

  1. static void default_do_nmi(struct pt_regs * regs)
  2. {
  3. ...
  4. if (nmi_watchdog) {
  5.             nmi_watchdog_tick(regs);
  6.             return;
  7. ...
  8. }
nmi_watchdog检测函数:nmi_watchdog_tick()

点击(此处)折叠或打开

  1. void nmi_watchdog_tick (struct pt_regs * regs)
  2. {
  3.     int sum, cpu = smp_processor_id();

  4.     sum = irq_stat[cpu].apic_timer_irqs;
  5. //检测irq计数是否更新,如果没更新,则表示可能发生关中断死锁了。
  6.     if (last_irq_sums[cpu] == sum) {
  7.         /*
  8.          * Ayiee, looks like this CPU is stuck ...
  9.          * wait a few IRQs (5 seconds) before doing the oops ...
  10.          */
  11.         alert_counter[cpu]++;
  12. //如果5s内,计数都没有更新,那就触发die_nmi(),最终会走panic流程。
  13.         if (alert_counter[cpu] == 5*nmi_hz)
  14.             die_nmi(regs, "NMI Watchdog detected LOCKUP");
  15.     } else {
  16.         last_irq_sums[cpu] = sum;
  17.         alert_counter[cpu] = 0;
  18.     }
  19. ...
  20. }


阅读(10741) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~