为什么可能导致睡眠的函数都不能在中断上下文中使用呢?【转】
转自:http://www.cnblogs.com/hoys/archive/2012/06/28/2567622.html
转自:http://blog.chinaunix.net/u1/49093/showart_1910189.html
这个问题有很多人问过,我看了下Linux得内核代码,原因如下:(当然我不能保证一定对,如果有牛人理解得更好,欢迎指正)
1、 中断处理的时候,不应该发生进程切换,因为在中断context中,唯一能打断当前中断handler的只有更高优先级的中断,它不会被进程打断,如果在 中断context中休眠,则没有办法唤醒它,因为所有的wake_up_xxx都是针对某个进程而言的,而在中断context中,没有进程的概念,没 有一个task_struct(这点对于softirq和tasklet一样),因此真的休眠了,比如调用了会导致block的例程,内核几乎肯定会死。
2、schedule()在切换进程时,保存当前的进程上下文(CPU寄存器的值、进程的状态以及堆栈中的内容),以便以后恢复此进程运行。中断发生后,内核会先保存当前被中断的进程上下文(在调用中断处理程序后恢复);
但在中断处理程序里,CPU寄存器的值肯定已经变化了吧(最重要的程序计数器PC、堆栈SP等),如果此时因为睡眠或阻塞操作调用了schedule(),则保存的进程上下文就不是当前的进程context了.所以不可以在中断处理程序中调用schedule()。
3、2.4内核中schedule()函数本身在进来的时候判断是否处于中断上下文:
if(unlikely(in_interrupt()))
BUG();
因此,强行调用schedule()的结果就是内核BUG,但我看2.6.18的内核schedule()的实现却没有这句,改掉了。
4、中断handler会使用被中断的进程内核堆栈,但不会对它有任何影响,因为handler使用完后会完全清除它使用的那部分堆栈,恢复被中断前的原貌。
5、处于中断context时候,内核是不可抢占的。因此,如果休眠,则内核一定挂起。
-------------------------------------------------------
原帖地址:http://bbs.chinaunix.net/thread-2115820-1-1.html
这里引用个人认为比较OK的解析:
呵呵,我最喜欢这种讨论了。先来献丑了,说说我的看法。
先把中断处理流程给出来
- 1.进入中断处理程序--->2.保存关键上下文---->3.开中断(sti指令)--->4.进入中断处理程序的 handler--->5.关中断(cli指令)---->6.写EOI寄存器(表示中断处理完成)---->7.开中断。
复制代码
硬中断:
对应于上图的1、2、3步骤,在这几个步骤中,所有中断是被屏蔽的,如果在这个时候睡眠了,操作系统不会收到任何中断(包括时钟中断),系统就基本处于瘫痪状态(例如调度器依赖的时钟节拍没有等等……)
软中断:
对应上图的4(当然,准确的说应该是4步骤的后面一点,先把话说保险点,免得思一克又开始较真 )。这个时候不能睡眠的关键是因为上下文。
大家知道操作系统以进程调度为单位,进程的运行在进程的上下文中,以进程描述符作为管理的数据结构。进程可以睡眠的原因是操作系统可以切换不同进程的上下文,进行调度操作,这些操作都以进程描述符为支持。
中断运行在中断上下文,没有一个所谓的中断描述符来描述它,它不是操作系统调度的单位。一旦在中断上下文中睡眠,首先无法切换上下文(因为没有中断描述符,当前上下文的状态得不到保存),其次,没有人来唤醒它,因为它不是操作系统的调度单位。
此外,中断的发生是非常非常频繁的,在一个中断睡眠期间,其它中断发生并睡眠了,那很容易就造成中断栈溢出导致系统崩溃。
如 果上述条件满足了(也就是有中断描述符,并成为调度器的调度单位,栈也不溢出了,理论上是可以做到中断睡眠的),中断是可以睡眠的,但会引起很多问题.例 如,你在时钟中断中睡眠了,那操作系统的时钟就乱了,调度器也了失去依据;例如,你在一个IPI(处理器间中断)中,其它CPU都在死循环等你答复,你确 睡眠了,那其它处理器也不工作了;例如,你在一个DMA中断中睡眠了,上面的进程还在同步的等待I/O的完成,性能就大大降低了……还可以举出很多例子。 所以,中断是一种紧急事务,需要操作系统立即处理,不是不能做到睡眠,是它没有理由睡眠。
======================================================
另一篇:
http://blog.openrays.org/blog.php?do=showone&tid=455
其结论:
5. 中断处理时可否睡眠问题
Linux 设计中,中断处理时不能睡眠,这个内核中有很多保护措施,一旦检测到内核会异常。
当 一个进程A因为中断被打断时,中断处理程序会使用 A 的内核栈来保存上下文,因为是“抢”的 A 的CPU,而且用了 A 的内核栈,因此中断应该尽可能快的结束。如果 do_IRQ 时又被时钟中断打断,则继续在 A 的内核栈上保存中断上下文,如果发生调度,则 schedule 进 switch_to,又会在 A 的 task_struct->thread_struct 里保存此时时种中断的上下文。
假如其是在睡眠时被时钟中断打断,并 schedule 的话,假如选中了进程 A,并 switch_to 过去,时钟中断返回后则又是位于原中断睡眠时的状态,抛开其扰乱了与其无关的进程A的运行不说,这里的问题就是:该如何唤醒之呢??
另外,和该中断共享中断号的中断也会受到影响。
======================================================
再一篇,也分析的很到位:
http://blog.csdn.net/maray/article/details/5770889
其结论:
Linux是以进程为调度单位的,调度器只看到进程内核栈,而看不到中断栈。在独立中断栈的模式下,如果linux内核在中断路径内发生了调度(从技术上讲,睡眠和调度是一个意思),那么linux将无法找到“回家的路”,未执行完的中断处理代码将再也无法获得执行机会。
本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5343933.html,如需转载请自行联系原作者
为什么可能导致睡眠的函数都不能在中断上下文中使用呢?【转】相关推荐
- python中标识符下划线用作开头_python python中那些双下划线开头的那些函数都是干啥用用的...
1.写在前面 今天遇到了__slots__,,所以我就想了解下python中那些双下划线开头的那些函数都是干啥用用的,翻到了下面这篇博客,看着很全面,我只了解其中的一部分,还不敢乱下定义. 其实如果足 ...
- 三种睡眠时间函数的区别:linux 的sleep()、usleep()、nanosleep()函数
三种睡眠时间函数的区别:linux 的sleep().usleep().nanosleep()函数 (1)sleep()-------以秒为单位 unsigned int sleep(unsigned ...
- python中那些双下划线开头的那些函数都是干啥用用的
1.写在前面 今天遇到了__slots__,,所以我就想了解下python中那些双下划线开头的那些函数都是干啥用用的,翻到了下面这篇博客,看着很全面,我只了解其中的一部分,还不敢乱下定义. 其实如果足 ...
- python属性名以两个下划线开头_python python中那些双下划线开头的那些函数都是干啥用用的...
1.写在前面 今天遇到了__slots__,,所以我就想了解下python中那些双下划线开头的那些函数都是干啥用用的,翻到了下面这篇博客,看着很全面,我只了解其中的一部分,还不敢乱下定义. 其实如果足 ...
- 为什么每个函数都要测试
也许有人会问为什么每个函数都要测试,现实中应该是不必要的吧?这个问题其实很简单,函数的编写,要能让测试驱动,就必须起码遵循两个原则: 1 不需要测试的函数,移除它,它不应该存在. 2 测试无法透彻的函 ...
- 字节跳动涉代码抄袭被诉陪22.74亿,连错误的函数都搬?
整理 | 程序员求职面试(ID:CoderJob) 来源 | 美摄科技.企查查.第一财经等 4月30日,美摄科技通过微信公众号发布声明,称近日已向法院以侵害计算机软件著作权及侵害技术秘密为由,正式起诉 ...
- 一个关于js所有函数都报错的问题
为什么80%的码农都做不了架构师?>>> 几个月没有做开发了,前不久刚接一个小活做开发,在一个jsp页面写的一段js代码,老是报上面的错,花费几个小时未解决,由于当时写代码是直 ...
- 原来在UNITY中使用system.io下的所有函数都可以用相对路径 : Assets/xx
原来在UNITY中使用system.io下的所有函数都可以用相对路径 : Assets/xx 代码如下图,这样就不用在绝对路径和相对路径之间不断转换了. 想要得到绝对路径时就傅 Application ...
- C++对C的加强之C++中所有的变量和函数都必须有类型
变量和函数都必须有类型 C++中所有的变量和函数都必须有类型 总结 C++中所有的变量和函数都必须有类型 /* C++中所有的变量和函数都必须有类型 C语言中的默认类型在C++中是不合法的 函数f的返 ...
最新文章
- ChannelFactory.Endpoint 上的地址属性为空。ChannelFactory 的终结点必须指定一个有效的地址。...
- Spring Boot学习笔记-基础(2)
- java中集合类的转换_Java中的两个常用工具类及集合数组的相互转换
- mfc通过信号量保证线程同步
- Gradle中的buildScript,gradle wrapper,dependencies等一些基础知识
- WebView性能优化--独立进程
- Dart 1(环境安装)
- php编译时出错make: *** [libphp5.la] Error 1
- C#中的深度学习:Keras.NET中的硬币识别,第一部分
- php链接mysql数据库
- element表格点击行即选中该行复选框
- m4s格式转换mp3_wma格式怎么转换mp3
- 为什么不吃米和面之后,体重掉得比较快?答案或许不是你想的那样
- 微信小程序图片加载太慢;uni-app微信小程序加载图片优化;微信小程序图片image加载成功事件@load;图片加载成功触发@load事件
- win10可用空间变成未分配_有关如何在win10系统中对未分配的磁盘空间进行分区的详细教程...
- 外汇市场百年风云演变,当代“钱”途之选就看EBC金融集团
- 如何删除oracle 的用户及其数据
- 看论文需要用到的一些专业词汇【SOTA,Benchmark,Baseline】
- ChatGPT:那些让美国伟大的俄罗斯人
- 四川大学软件学院|系统级编程期末复习