关于might_sleep的一点说明
2015-09-15 08:37
369 查看
这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过因为内核中很多函数一开始就会用一下它,为了方便那些正在学习内核源码的网友,本帖专门讨论一下该函数到底被内核用来干什么。
简单地说,如果没有调试的需求(绝大多数下你平常跑的系统都是release版本的kernel),那么这个宏(或者函数,称谓并不重要)什么实质性的活都不干,内核只是用它来做一件事,就是提醒你,调用该函数的函数可能会sleep,这个跟其名字也是匹配的: The function calling
might_sleep() might sleep。如果你想看源码,我把它列在下面:
点击(此处)折叠或打开
# define might_resched() do { } while (0)
# 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又有哪些特殊的功能呢?先看看内核中的源码:
点击(此处)折叠或打开
void __might_sleep(const char *file, int line, int preempt_offset)
{
static unsigned long prev_jiffy; /* ratelimiting */
if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
system_state != SYSTEM_RUNNING || oops_in_progress)
return;
if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
return;
prev_jiffy = jiffies;
printk(KERN_ERR
"BUG: sleeping function called from invalid context at %s:%d\n",
file, line);
printk(KERN_ERR
"in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
in_atomic(), irqs_disabled(),
current->pid, current->comm);
if (irqs_disabled())
print_irqtrace_events(current);
dump_stack();
}
上面的代码我进行了轻微的删减,去除了一些只有CONFIG_DEBUG_ATOMIC_SLEEP选项使能的情形下不干活的函数。
点击(此处)折叠或打开
# define might_sleep() \
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型变量,主要用来记录当前系统的状态:
点击(此处)折叠或打开
enum system_states system_state __read_mostly;
EXPORT_SYMBOL(system_state);
注意system_state已经被export出来,所以内核模块可以直接读该值来判断当前系统的运行状态,常见的状态包括:
点击(此处)折叠或打开
extern enum system_states {
SYSTEM_BOOTING,
SYSTEM_RUNNING,
SYSTEM_HALT,
SYSTEM_POWER_OFF,
SYSTEM_RESTART,
SYSTEM_SUSPEND_DISK,
} system_state;
最常见的状态当然是SYSTEM_RUNNING了,你的系统正常起来之后就处于这个状态。因为跟当前的话题没有直接的关联,这里只提一下好了。
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
阅读(1) | 评论(0) | 转发(0) |
0
上一篇:proc函数
下一篇:linux程序设计---多线程
相关热门文章
linux 常见服务端口
【ROOTFS搭建】busybox的httpd...
xmanager 2.0 for linux配置
什么是shell
linux socket的bug??
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
简单地说,如果没有调试的需求(绝大多数下你平常跑的系统都是release版本的kernel),那么这个宏(或者函数,称谓并不重要)什么实质性的活都不干,内核只是用它来做一件事,就是提醒你,调用该函数的函数可能会sleep,这个跟其名字也是匹配的: The function calling
might_sleep() might sleep。如果你想看源码,我把它列在下面:
点击(此处)折叠或打开
# define might_resched() do { } while (0)
# 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又有哪些特殊的功能呢?先看看内核中的源码:
点击(此处)折叠或打开
void __might_sleep(const char *file, int line, int preempt_offset)
{
static unsigned long prev_jiffy; /* ratelimiting */
if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
system_state != SYSTEM_RUNNING || oops_in_progress)
return;
if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
return;
prev_jiffy = jiffies;
printk(KERN_ERR
"BUG: sleeping function called from invalid context at %s:%d\n",
file, line);
printk(KERN_ERR
"in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
in_atomic(), irqs_disabled(),
current->pid, current->comm);
if (irqs_disabled())
print_irqtrace_events(current);
dump_stack();
}
上面的代码我进行了轻微的删减,去除了一些只有CONFIG_DEBUG_ATOMIC_SLEEP选项使能的情形下不干活的函数。
点击(此处)折叠或打开
# define might_sleep() \
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型变量,主要用来记录当前系统的状态:
点击(此处)折叠或打开
enum system_states system_state __read_mostly;
EXPORT_SYMBOL(system_state);
注意system_state已经被export出来,所以内核模块可以直接读该值来判断当前系统的运行状态,常见的状态包括:
点击(此处)折叠或打开
extern enum system_states {
SYSTEM_BOOTING,
SYSTEM_RUNNING,
SYSTEM_HALT,
SYSTEM_POWER_OFF,
SYSTEM_RESTART,
SYSTEM_SUSPEND_DISK,
} system_state;
最常见的状态当然是SYSTEM_RUNNING了,你的系统正常起来之后就处于这个状态。因为跟当前的话题没有直接的关联,这里只提一下好了。
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
阅读(1) | 评论(0) | 转发(0) |
0
上一篇:proc函数
下一篇:linux程序设计---多线程
相关热门文章
linux 常见服务端口
【ROOTFS搭建】busybox的httpd...
xmanager 2.0 for linux配置
什么是shell
linux socket的bug??
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
相关文章推荐
- proc函数
- 三星S3C2440 Datasheet LCD Controller 章节翻译(2)
- Linux/stat.h 读写权限
- 菜鸟编译Linux内核
- printk及控制台的日志级别
- 对linux字符设备的理解(整体架构)
- superblock,file,dentry,inode的区别
- va_start va_end 的使用和原理
- class.c重要函数浅析
- linux字符cdev和Inode的关系
- Makefile
- kzalloc详解
- Linux内核入门—— __attribute__ 机制
- 基于MTD的NAND驱动开发
- MTD子系统归纳总结
- 深度分析NandFlash—控制器参数TACLS、TWRPH0和TWRPH1的确定(以TQ2440开发板上的K9F2G08U0A为例)
- 解读x86、ARM和MIPS三种主流芯片架构
- Ubuntu通过使用PyCharm 进行调试 Odoo 8.0 可能出现的问题
- O(∩_∩)O~
- hdu 5441 Travel(并查集应用)