转自:http://blog.csdn.net/chen_chuang_/article/details/48462575

这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过因为内核中很多函数一开始就会用一下它,为了方便那些正在学习内核源码的网友,本帖专门讨论一下该函数到底被内核用来干什么。

简单地说,如果没有调试的需求(绝大多数下你平常跑的系统都是release版本的kernel),那么这个宏(或者函数,称谓并不重要)什么实质性的活都不干,内核只是用它来做一件事,就是提醒你,调用该函数的函数可能会sleep,这个跟其名字也是匹配的:
The function calling might_sleep() might sleep。如果你想看源码,我把它列在下面:

点击(此处)折叠或打开

  1. # define might_resched()
    do {
    } while (0)
  2. # define might_sleep()
    do { might_resched();
    } while
    (0)

看到没,啥事都没干。其实内核源码对此也有明确的注释:might_sleep
- annotation for functions that can sleep。所以对于release版的kernel
image而言,might_sleep的作用仅仅是一个annotation,提醒使用者,一个使用might_sleep的函数在其后的代码执行中可能会sleep。

不过如果有调试需求介入的话,比如你的系统莫名其妙地随机性地crash掉,在经过一段艰难的案情分析排查之后,最后你决定打开内核的CONFIG_DEBUG_ATOMIC_SLEEP选项,那么此时might_sleep对案情的进一步推进就可能产生贡献了。CONFIG_DEBUG_ATOMIC_SLEEP选项主要用来排查是否在一个ATOMIC操作的上下文中有函数发生sleep行为,关于什么是ATOMIC操作,内核源码在might_sleep函数前也有一段注释:
this macro will print a stack trace if it is executed in an atomic context (spinlock, irq-handler, ...)

所以很明显,一个进程获得了spinlock之后它就进入了这里所谓的atomic
context,或者是在一个irq-handler,也就是一个中断上下文中。这两种上下文中理论上不应该让当前的execution
path进入sleep状态(虽然不是强制规定,换句话说,一个拥有spinlock的进程进入sleep并不必然意味着系统就一定会deadlock等,但是对内核编程而言,还是应该尽力避开这个雷区)。

在CONFIG_DEBUG_ATOMIC_SLEEP选项打开的情形下,might_sleep又有哪些特殊的功能呢?先看看内核中的源码:

点击(此处)折叠或打开

  1. void __might_sleep(const char
    *file,
    int line, int preempt_offset)
  2. {
  3. static unsigned long prev_jiffy;
    /* ratelimiting
    */
  4. if
    ((preempt_count_equals(preempt_offset)
    &&
    !irqs_disabled())
    ||
  5. system_state
    != SYSTEM_RUNNING
    || oops_in_progress)
  6. return;
  7. if
    (time_before(jiffies, prev_jiffy
    + HZ)
    && prev_jiffy)
  8. return;
  9. prev_jiffy
    = jiffies;
  10. printk(KERN_ERR
  11. "BUG: sleeping function called from invalid context at %s:%d\n",
  12. file, line);
  13. printk(KERN_ERR
  14. "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
  15. in_atomic(), irqs_disabled(),
  16. current->pid, current->comm);
  17. if
    (irqs_disabled())
  18. print_irqtrace_events(current);
  19. dump_stack();
  20. }

上面的代码我进行了轻微的删减,去除了一些只有CONFIG_DEBUG_ATOMIC_SLEEP选项使能的情形下不干活的函数。

点击(此处)折叠或打开

  1. # define might_sleep()
    \
  2. do
    { __might_sleep(__FILE__, __LINE__, 0); might_resched();
    } while
    (0)

在当前CONFIG_DEBUG_ATOMIC_SLEEP选项使能的前提下,
可以看到__might_sleep还是干了不少事情的,最主要的工作是在第一个if语句那里,尤其是preempt_count_equals和
irqs_disabled,都是用来判断当前的上下文是否是一个atomic
context,因为我们知道,只要进程获得了spin_lock的任一个变种形式的lock,那么无论是单处理器系统还是多处理器系统,都会导致preempt_count发生变化,而irq_disabled则是用来判断当前中断是否开启。__might_sleep正是根据这些信息来判断当前正在执行的代码上下文是否是个atomic,如果不是,那么函数就直接返回了,因为一切正常。如果是,那么代码下行。

所以让CONFIG_DEBUG_ATOMIC_SLEEP选项打开,可以捕捉到在一个atomic
context中是否发生了sleep,如果你的代码不小心在某处的确出现了这种情形,那么might_sleep会通过后续的printk以及dump_stack来协助你发现这种情形。

至于__might_sleep函数中的system_state,它是一个全局性的enum型变量,主要用来记录当前系统的状态:

点击(此处)折叠或打开

  1. enum system_states system_state __read_mostly;
  2. EXPORT_SYMBOL(system_state);

注意system_state已经被export出来,所以内核模块可以直接读该值来判断当前系统的运行状态,常见的状态包括:

点击(此处)折叠或打开

  1. extern enum system_states
    {
  2. SYSTEM_BOOTING,
  3. SYSTEM_RUNNING,
  4. SYSTEM_HALT,
  5. SYSTEM_POWER_OFF,
  6. SYSTEM_RESTART,
  7. SYSTEM_SUSPEND_DISK,
  8. } system_state;

最常见的状态当然是SYSTEM_RUNNING了,你的系统正常起来之后就处于这个状态。因为跟当前的话题没有直接的关联,这里只提一下好了。

阅读(1) | 评论(0) | 转发(0) |

0

上一篇:proc函数

下一篇:linux程序设计---多线程

评论热议

关于might_sleep的一点说明【转】的更多相关文章

  1. 关于might_sleep的一点说明---CONFIG_DEBUG_ATOMIC_SLEEP【转】

    转自:http://blog.chinaunix.net/uid-23769728-id-3157536.html 这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过因为内核 ...

  2. 关于自己写C++的一点风格

    现在,我学了很长时间的C++,但是自己就是无法精通.许多知识是入门书上没有的.现在写C++最重要的就是风格问题. 我现在的C++风格: 把自己所有的东西都放在一个名称空间下. 没有全局的函数,有的函数 ...

  3. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  4. 一点公益商城开发系统模式Ring Buffer+

    一个队列如果只生产不消费肯定不行的,那么如何及时消费Ring Buffer的数据呢?简单的方案就是当Ring Buffer"写满"的时候一次性将数据"消费"掉. ...

  5. SVM一点心得体会

    支持向量机的学习说是刚刚开始,又不合理,只能说隔了很长的时间再看,终于在分类这块的层面上有了新的认识. 总的来说,支持向量机分为线性支持向量机和非线性支持向量机,线性支持向量机又可以分为硬间隔最大化线 ...

  6. [网站性能1]对.net系统架构改造的一点经验和教训

    文章来源:http://www.admin10000.com/document/2111.html 在互联网行业,基于Unix/Linux的网站系统架构毫无疑问是当今主流的架构解决方案,这不仅仅是因为 ...

  7. 关于js的回调函数的一点看法

    算了一下又有好几个月没写博客了,最近在忙公司android的项目,所以也就很少抽时间来写些东西了.刚闲下来,我就翻了翻之前看的东西.做了android之后更加感觉到手机端开发的重要性,现在做nativ ...

  8. .NET支持多平台后的一点拙见

    我们目前对.NET的理解大部分可以归纳为:起初它是Java平台(注意是平台,不要跟Java语言搞混淆)的一个克隆品,后来慢慢演变,有了自己的特性.由于Java平台最显著的特点就是“平台独立性”(或者说 ...

  9. 每天多一点(2016.12.04)》Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

随机推荐

  1. Delphi Dataset CurValue

    TField.CurValue Property Represents the current value of the field component including changes made ...

  2. table中的td限制宽度width也不能让字符过长变成省略号生效?

    table中的td限制宽度width也不能让字符过长变成省略号生效? http://blog.csdn.net/java_mr_zheng/article/details/49423247 CSS t ...

  3. 使用mac电脑,对Github客户端的简单操作1----开源项目

    工作之余自己也会一写一些小的程序项目,由于一直没时间“折腾”开源,之前写博客都是直接粘代码片段,今天看别人写技术博客大都会放出项目Github地址,突然感觉自己有点点out and low,作为一个励 ...

  4. Linq里where出现null的问题

    今天遇到一个问题,怎么在where里判断一个字段是否为null,并且这个字段不是字符串string类型,而是int和GUID类型,折腾了半天终于搞明白了.(由于项目是我半路接手的,问题是前期的同事给我 ...

  5. 【题解】洛谷P4735最大异或和

    学习了一下可持久化trie的有关姿势~其实还挺好理解的,代码也短小精悍.重点在于查询某个历史版本的trie树上的某条边是否存在,同样我们转化到维护前缀和来实现.同可持久化线段树一样,我们为了节省空间继 ...

  6. [AHOI2014/JSOI2014]支线剧情 有上下界费用流

    ---题面--- 题解: 第一眼费用流,,然后想了好久怎么建图,,,最后发现是最小费用可行流的板子题.... 其实还没有很懂这个算法,所以这里只是摆一下步骤,以后再补理解吧. 首先一个思路就是转换图, ...

  7. 用camke编译python程序

    project(test) cmake_minimum_required(VERSION 3.0) find_package(OpenCV REQUIRED) find_package (Python ...

  8. 安卓弹出键盘隐藏fixed定位相关的元素(obj必须是class)

    //安卓弹出键盘隐藏fixed定位相关的元素(obj必须是class) function displayFixed(obj){ var h = document.body.scrollHeight; ...

  9. 51Nod 1083 矩阵取数问题 | 动态规划

    #include "bits/stdc++.h" using namespace std; #define LL long long #define INF 0x3f3f3f3f3 ...

  10. 【C++对象模型】第五章 构造、解构、拷贝 语意学

    1.构造语义学 C++的构造函数可能内带大量的隐藏码,因为编译器会扩充每一个构造函数,扩充程度视 class 的继承体系而定.一般而言编译器所做的扩充操作大约如下: 所有虚基类成员构造函数必须被调用, ...