“BUG: sleeping function called from invalid context at ......”(might_sleep函数说明)
来源:互联网 发布:js获取边框宽度 编辑:程序博客网 时间:2024/05/20 20:04
我们在调试Linux kernel驱动时经常会遇到如下LOG信息:
[ 88.055297] BUG: sleeping function called from invalid context at ......
这个错误就是在might_sleep函数中打印的,关于这个函数的说明,查了下资料归结如下:
这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过因为内核中很多函数一开始就会用一下它,为了方便那些正在学习内核源码的网友,本帖专门讨论一下该函数到底被内核用来干什么。
简单地说,如果没有调试的需求(绝大多数下你平常跑的系统都是release版本的kernel),那么这个宏(或者函数,称谓并不重要)什么实质性的活都不干,内核只是用它来做一件事,就是提醒你,调用该函数的函数可能会sleep,这个跟其名字也是匹配的: The function calling might_sleep() might sleep。这个函数的定义如下:
#ifdef CONFIG_PREEMPT_VOLUNTARYextern int _cond_resched(void);# define might_resched() _cond_resched()#else# define might_resched() do { } while (0)#endif#ifdef CONFIG_DEBUG_ATOMIC_SLEEP void __might_sleep(const char *file, int line, int preempt_offset);/** * might_sleep - annotation for functions that can sleep * * this macro will print a stack trace if it is executed in an atomic * context (spinlock, irq-handler, ...). * * This is a useful debugging help to be able to catch problems early and not * be bitten later when the calling function happens to sleep when it is not * supposed to. */# define might_sleep() \do { __might_sleep(__FILE__, __LINE__, 0); might_resched(); } while (0)#else static inline void __might_sleep(const char *file, int line, int preempt_offset) { }# define might_sleep() do { might_resched(); } while (0)#endif
其实内核源码对此也有明确的注释: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, ...)
void __might_sleep(const char *file, int line, int preempt_offset){static unsigned long prev_jiffy;/* ratelimiting */rcu_sleep_check(); /* WARN_ON_ONCE() by default, no rate limit reqd. */if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) || oops_in_progress)return;if (system_state != SYSTEM_RUNNING && (!__might_sleep_init_called || system_state != SYSTEM_BOOTING))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);debug_show_held_locks(current);if (irqs_disabled())print_irqtrace_events(current);dump_stack();}EXPORT_SYMBOL(__might_sleep);
在当前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型变量,主要用来记录当前系统的状态。注意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了,你的系统正常起来之后就处于这个状态。因为跟当前的话题没有直接的关联,这里只提一下好了。- “BUG: sleeping function called from invalid context at ......”(might_sleep函数说明)
- 解决“User breakpoint called from code at XXXX”Bug
- 解决“User breakpoint called from code at XXXX”Bug
- 解决“User breakpoint called from code at XXXX”Bug
- user breakpoint called from code at
- User breakpoint called from code at
- user breakpoint called from code at ....
- User breakpoint called from code at ***
- 关于might_sleep的一点说明
- 关于might_sleep的一点说明
- 关于might_sleep的一点说明
- CGContextSetFillColorWithColor: invalid context 0x0. 类似BUG!
- might_sleep()
- might_sleep()
- might_sleep
- user breakpoint called from code at 0x******
- user breakpoint called from code at 0x...
- User breakpoint called from code at 0x77fa018c解释
- 01背包问题优化
- java管道使用
- OCP-1Z0-052-V8.02-162题
- 2013-10-12.笔记001
- POJ 3342 Party at Hali-Bula(树形DP)
- “BUG: sleeping function called from invalid context at ......”(might_sleep函数说明)
- Oracle批量创建用户和导入导出的脚本
- Android 序列化 Parcelable
- my2DAlloc
- Linux中主dns和辅dns服务器的简单配置
- 给VMWare中的Windows XP分区
- 关于web安全之sql注入攻击
- 13个代码注释的小技巧
- 电磁波的发射和接收