转自:http://www.cnblogs.com/openix/p/4034530.html

转自:http://blog.csdn.net/panzhenjie/article/details/10074551/

在linux kernel里,有一个debug选项LOCKUP_DETECTOR。

使能它可以打开kernel中的soft lockup和hard lockup探测。

这两个东西到底有什么用处那?

首先,soft/hard lockup的实现在kernel/watchdog.c中,

主体涉及到了3个东西:kernel线程,时钟中断,NMI中断(不可屏蔽中断)。

这3个东西具有不一样的优先级,依次是kernel线程 < 时钟中断 < NMI中断。

而正是用到了他们之间优先级的区别,所以才可以调试系统运行中的两种问题:

1. 抢占被长时间关闭而导致进程无法调度(soft lockup)

2. 中断被长时间关闭而导致更严重的问题(hard lockup)

接下来我们从具体代码入手分析linux(3.10)是如何实现这两种lockup的探测的:

  1. static struct smp_hotplug_thread watchdog_threads = {
  2. .store          = &softlockup_watchdog,
  3. .thread_should_run  = watchdog_should_run,
  4. .thread_fn      = watchdog,
  5. .thread_comm        = "watchdog/%u",
  6. .setup          = watchdog_enable,
  7. .park           = watchdog_disable,
  8. .unpark         = watchdog_enable,
  9. };
  10. void __init lockup_detector_init(void)
  11. {
  12. set_sample_period();
  13. if (smpboot_register_percpu_thread(&watchdog_threads)) {
  14. pr_err("Failed to create watchdog threads, disabled\n");
  15. watchdog_disabled = -ENODEV;
  16. }
  17. }

首先,系统会为每个cpu core注册一个一般的kernel线程,名字叫watchdog/0, watchdog/1...以此类推。

这个线程会定期得调用watchdog函数

  1. static void __touch_watchdog(void)
  2. {
  3. __this_cpu_write(watchdog_touch_ts, get_timestamp());
  4. }
  5. static void watchdog(unsigned int cpu)
  6. {
  7. __this_cpu_write(soft_lockup_hrtimer_cnt,
  8. __this_cpu_read(hrtimer_interrupts));
  9. __touch_watchdog();
  10. }

我们先不理会这个线程处理函数watchdog多久被调用一次,我们就先简单的认为,这个线程是负责更新watchdog_touch_ts的。

然后我们要看一下时钟中断了:

  1. static void watchdog_enable(unsigned int cpu)
  2. {
  3. struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
  4. /* kick off the timer for the hardlockup detector */
  5. hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  6. hrtimer->function = watchdog_timer_fn;
  7. /* done here because hrtimer_start can only pin to smp_processor_id() */
  8. hrtimer_start(hrtimer, ns_to_ktime(sample_period),
  9. HRTIMER_MODE_REL_PINNED);
  10. }

时钟中断处理函数是watchdog_timer_fn

  1. static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
  2. {
  3. unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
  4. int duration;
  5. /* kick the hardlockup detector */
  6. watchdog_interrupt_count();
  7. duration = is_softlockup(touch_ts);
  8. if (unlikely(duration)) {
  9. if (softlockup_panic)
  10. panic("softlockup: hung tasks");
  11. __this_cpu_write(soft_watchdog_warn, true);
  12. } else
  13. __this_cpu_write(soft_watchdog_warn, false);
  14. return HRTIMER_RESTART;
  15. }

这个函数主要做2件事情:

1. 更新hrtimer_interrupts变量。

  1. static void watchdog_interrupt_count(void)
  2. {
  3. __this_cpu_inc(hrtimer_interrupts);
  4. }

这里我们就要回顾之前创建的那个kernel线程了,多久调用一次就和hrtimer_interrupts的值密切相关。

  1. static int watchdog_should_run(unsigned int cpu)
  2. {
  3. return __this_cpu_read(hrtimer_interrupts) !=
  4. __this_cpu_read(soft_lockup_hrtimer_cnt);
  5. }

只有在hrtimer_interrupts发生了更新的情况下,kernel线程才会被得到运行。

那就是说,kernel线程和时钟中断函数的频率是相同的。默认情况是10*2/5=4秒一次。

  1. int __read_mostly watchdog_thresh = 10;
  2. static int get_softlockup_thresh(void)
  3. {
  4. return watchdog_thresh * 2;
  5. }
  6. static void set_sample_period(void)
  7. {
  8. /*
  9. * convert watchdog_thresh from seconds to ns
  10. * the divide by 5 is to give hrtimer several chances (two
  11. * or three with the current relation between the soft
  12. * and hard thresholds) to increment before the
  13. * hardlockup detector generates a warning
  14. */
  15. sample_period = get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5);
  16. }

2.就是要探测是否有soft lockup发生。

  1. static int is_softlockup(unsigned long touch_ts)
  2. {
  3. unsigned long now = get_timestamp();
  4. /* Warn about unreasonable delays: */
  5. if (time_after(now, touch_ts + get_softlockup_thresh()))
  6. return now - touch_ts;
  7. return 0;
  8. }

很容易理解,其实就是查看watchdog_touch_ts变量在最近20秒的时间内,有没有被创建的kernel thread更新过。

假如没有,那就意味着线程得不到调度,所以很有可能就是在某个cpu core上抢占被关闭了,所以调度器没有办法进行调度。

这种情况下,系统往往不会死掉,但是会很慢。

有了soft lockup的机制,我们就能尽早的发现这样的问题了。

分析完soft lockup,我们继续分析hard lockup

  1. static int watchdog_nmi_enable(unsigned int cpu)
  2. {
  3. struct perf_event_attr *wd_attr;
  4. wd_attr = &wd_hw_attr;
  5. wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
  6. /* Try to register using hardware perf events */
  7. event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
  8. }

perf_event_create_kernel_counter函数主要是注册了一个硬件的事件。

这个硬件在x86里叫performance monitoring,这个硬件有一个功能就是在cpu clock经过了多少个周期后发出一个NMI中断出来。

  1. u64 hw_nmi_get_sample_period(int watchdog_thresh)
  2. {
  3. return (u64)(cpu_khz) * 1000 * watchdog_thresh;
  4. }

在这里,根据当前cpu的频率,算出一个值,也就是20秒cpu clock经过的周期数。

这样一来,当cpu全负荷跑完20秒后,就会有一个NMI中断发出,而这个中断的出路函数就是watchdog_overflow_callback。

  1. static void watchdog_overflow_callback(struct perf_event *event,
  2. struct perf_sample_data *data,
  3. struct pt_regs *regs)
  4. {
  5. if (is_hardlockup()) {
  6. int this_cpu = smp_processor_id();
  7. if (hardlockup_panic)
  8. panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
  9. else
  10. WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
  11. return;
  12. }
  13. return;
  14. }

这个函数主要就是调用is_hardlockup

  1. static int is_hardlockup(void)
  2. {
  3. unsigned long hrint = __this_cpu_read(hrtimer_interrupts);
  4. if (__this_cpu_read(hrtimer_interrupts_saved) == hrint)
  5. return 1;
  6. __this_cpu_write(hrtimer_interrupts_saved, hrint);
  7. return 0;
  8. }

而这个函数主要就是查看hrtimer_interrupts变量在时钟中断处理函数里有没有被更新。

假如没有更新,就意味着中断出了问题,可能被错误代码长时间的关中断了。
那这样,相应的问题也就暴露出来了。

soft lockup和hard lockup介绍的更多相关文章

  1. 内核如何检测SOFT LOCKUP与HARD LOCKUP?

    内核如何检测SOFT LOCKUP与HARD LOCKUP? From article 所谓lockup,是指某段内核代码占着CPU不放.Lockup严重的情况下会导致整个系统失去响应.Lockup有 ...

  2. Linux soft lockup 和 hard lockup

    一. 整体介绍 soft lockup:检测调度异常, 一般是驱动禁止调度或者阻塞比如while(1), 导致无法调度其他线程, 需要注意的是, 应用程序while(1)不会影响其调度, 只要有更高的 ...

  3. CentOS7运行报错kernel:NMI watchdog: BUG: soft lockup - CPU#0 stuck for 26s

    CentOS内核,对应的文件是/proc/sys/kernel/watchdog_thresh.CentOS内核和标准内核还有一个地方不一样,就是处理CPU占用时间过长的函数,CentOS下是watc ...

  4. 报错kernel:NMI watchdog: BUG: soft lockup - CPU#0 stuck for 26s

    近期在服务器跑大量高负载程序,造成cpu soft lockup.如果确认不是软件的问题. 解决办法: #追加到配置文件中 echo 30 > /proc/sys/kernel/watchdog ...

  5. C/C++ 介绍的PE文件遍历工具

    在前面的笔记中,我总结了Pe结构的一些结构含义,并手动编写了几段PE结构遍历代码,这里我直接把之前的C语言代码进行了封装,形成了一个命令行版的PE文件查看工具,该工具只有20kb,但却可以遍历出大部分 ...

  6. cpu资源长期使用率过高导致系统内核锁问题

    服务器跑大量高负载程序,会造成cpu soft lockup. 解决办法: #追加到配置文件中 echo 30 > /proc/sys/kernel/watchdog_thresh #查看 [r ...

  7. Linux网络驱动--snull

    snull是<Linux Device Drivers>中的一个网络驱动的例子.这里引用这个例子学习Linux网络驱动. 因为snull的源码,网上已经更新到适合最新内核,而我自己用的还是 ...

  8. 基于 CodeIgniter 的各类开源项目大全

    名称:STBlog 介绍:STBlog 是一套由CI中国社区驱动,基于Codeigniter MVC 框架编写的多权限博客系统,轻巧/快速/安全/易拓展/界面友好是它的最大特点. 官方:http:// ...

  9. 企业建站系统MiinCMP1.0.5 版公布!

    2014-5-4,在青年节,Juuluu公布了其企业建站系统的新版1.0.5,经过两周多的奋战,Juuluu团队为MiinCMP新浪云版的移植工作做了大量工作.1.0.5已可完美执行于国内免费的jav ...

随机推荐

  1. 深入了解A*

    一.前言 在这里我将对A*算法的实际应用进行一定的探讨,并且举一个有关A*算法在最短路径搜索的例子.值得注意的是这里并不对A*的基本的概念作介绍,如果你还对A*算法不清楚的话,请看姊妹篇<初识A ...

  2. hdu 1261 字串数

    解题思路:ACM紫书 第十章 P319 有重复元素的全排列 答案: 所有数的和的阶乘 除以 每个数阶乘的乘积 因为给定 (26*12)! 会爆掉(long long),这里用java 的BigInte ...

  3. cmd批处理常用符号详解

    cmd批处理常用符号详解 作者: 字体:[增加 减小] 类型:转载 我们在批处理编写过程中经常遇到各种特殊符号,很多朋友不是很清楚cmd中特殊符号的含义,这里简单的介绍下,方便需要的朋友   1.@一 ...

  4. 单机安装TFS(转载)

    一.安装操作系统:windows server 2003 + Sp2具体步骤: 1.安装windows server 2003时选用工作组(默认为workgroup).由于在工作组环境中部署,因此使用 ...

  5. Google搜索命令语法大全

    以下是目前所有的Google搜索命令语法,它不同于Google的帮助文档,因为这里介绍 了几个Google不推荐使用的命令语法.大多数的Google搜索命令语法有它特有的使用格式,希望大家能正确使用. ...

  6. Java finally语句到底是在return之前还是之后执行?

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下fina ...

  7. GPRS GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可用的一种移动数据业务,属于第二代移动通信中的数据传输技术

    GPRS 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可 ...

  8. asp.net缓存(转)

    转自:http://www.cnblogs.com/knowledgesea/archive/2012/06/20/2536603.html 一.缓存概念,缓存的好处.类型.            缓 ...

  9. alipay iOS SDK

    我也是醉了,进支付宝主页找都找不到,好不容易找到赶紧记下来:https://b.alipay.com/order/productDetail.htm?productId=201308060460965 ...

  10. iOS 用instancetype代替id作返回类型有什么好处?

    2014-07-07更新:苹果在iOS 8中全面使用instancetype代替id Steven Fisher:只要一个类返回自身的实例,用instancetype就有好处. @interface ...