Chinaunix

标题: 中断处理程序运行时为啥不能发生进程切换? [打印本页]

作者: faku    时间: 2011-03-23 20:29
标题: 中断处理程序运行时为啥不能发生进程切换?
《深入理解linux内核》中有这样一段话(大意):

中断处理程序可以嵌套, 但是是有代价的, 那就是中断处理程序运行时不能发生进程切换,
因为中断处理程序使用当前进程的内核栈......

上面的话我都能理解, 除了"中断处理程序运行时不能发生进程切换", (抛开中断处理程序可能会
修改内核数据结构这个原因
), 难道仅仅因为中断处理程序运行在当前进程的上下文, 就不能发生切换吗?
假设发生进程切换, 保存了所有的寄存器, 切换回来时候, 当然就切换回了原进程使用的内核栈,
不是照样可以从切换出去的点重新运行吗?
作者: L_kernel    时间: 2011-03-23 22:12
因为中断是代表进程执行的。
作者: yuanlulu3614    时间: 2011-03-23 22:30
如果中断使用进程栈,那么如果允许进程切换,中断怎么判断当前进程是不是自己中断的进程,况且如果进程切换出去之后就结束了,中断就永远无法执行。

貌似现在的内核使用一个单独的中断栈了,不再和进程共用。
作者: yuanlulu3614    时间: 2011-03-23 22:32
深入理解linux内核 这本书的部分内容落伍了
作者: faku    时间: 2011-03-24 07:31
中断处理程序代表当前进程运行这不假, 切换出去后, 当被挂起的进程重新运行后, 中断处理程序仍旧可以被执行啊, 怎么会永远也不能被运行呢?
作者: wkq5325    时间: 2011-03-24 08:09
中断本来就是个急事要处理,你再进程切换就没啥作用了,那就不叫中断了。
网卡要接受数据,还没处理呢,你就切换别的进程了(如果),,那网卡情何以堪。
而且中断不考虑打断的是谁,你如何再切回去。。。
作者: amarant    时间: 2011-03-24 11:14
是不是因为中断上下文不是一个调度的单位?
作者: amarant    时间: 2011-03-24 11:29
回复 5# faku


    貌似是因为这个进程有可能会被销毁了,那就永远回不去来了
作者: tempname2    时间: 2011-03-24 13:05
可以看看精华里面关于"中断中不能睡眠原因"的讨论.ULK里这样说似乎欠妥,中断中不能睡眠是应该设计的结果.
作者: seurobot    时间: 2011-03-24 17:32
是不是因为中断上下文不是一个调度的单位?
amarant 发表于 2011-03-24 11:14



    是的,当采用8KB的Kernel Stack时,中断的执行是建立在当前的Process Kernel Stack上的。一旦发生Context Switch将无法切换回来。
作者: amarant    时间: 2011-03-24 17:36
回复 10# seurobot


    那如果被中断的进程一直存在(没有销毁)也不能切换回来吗?
作者: seurobot    时间: 2011-03-24 17:44
回复 11# amarant


    被中断的进程在中断退出时由Scheduler决定是否再继续进行
作者: 木叉叉木大    时间: 2011-03-24 17:56
当执行一个中断处理程序或下半部时,内核处于终端上下文。中断上下文与进程没有啥关系。切换出去就回不来了。不像进程可以随意切换。下半部中工作队列可以睡眠所以可以切换。
作者: faku    时间: 2011-03-24 18:42
我想这也是设计结果!

其实, 从常理上说, 中断代表一个紧急小事件, 当然不需要睡眠、当然要快速执行,切换进程没有意义

假如当前进程一直存在, 如果我有办法保存所有的寄存器, 当然可以恢复所有的寄存器以保证从切换点继续执行

之所以不能睡眠,不能切换进程, 我想这是linux内核特点决定的吧
作者: Fleurer    时间: 2011-03-24 19:57
不是不能发生进程切换,是在中断处理中发生睡眠不好。

之所以有中断发生,除了系统时钟等等,就是像read/write这样“耗时”的系统调用了。比如调用了一个read,发出一个读盘请求,然后这个进程就睡眠了,在一个队列里等待某个事件发生(uninterruptible sleep)。也就是等着中断发生再回来唤醒它。

好了,这个进程睡眠了。但是中断在什么时候发生呢?

其它进程里。也就是说,某个中断发生的时候,当前的执行环境绝对不是等待它的那个进程。要是在这里睡眠了,就会把这个无关的进程放进了等待队列,无辜地被修改了状态。个人感觉这样不一定会直接导致内核无法运行,但是可能会带来一些不可预知的问题。
作者: jiangzj123    时间: 2011-03-25 10:19
不是不能发生进程切换,是在中断处理中发生睡眠不好。

之所以有中断发生,除了系统时钟等等,就是像read ...
Fleurer 发表于 2011-03-24 19:57


睡眠不就是要进行进程切换么?
作者: jiangzj123    时间: 2011-03-25 10:24
中断步骤:1保护现场,2执行中断函数,3恢复现场。个人理解,在进程A运行时,发生了中断,然后保护现场你,在执行中断函数中进行了进程切换,切换到B进程了,等中断函数执行完毕,恢复现场却是进程A的内容,结果可想而知了。个人理解,仅供参考。
作者: faku    时间: 2011-03-25 14:39
时钟中断处理程序里, 不就切换进程了吗?
作者: faku    时间: 2011-03-25 14:44
中断步骤:1保护现场,2执行中断函数,3恢复现场。个人理解,在进程A运行时,发生了中断,然后保护现场你, ...
jiangzj123 发表于 2011-03-25 10:24



切换到B, B就开始运行了, 也就是中断处理程序被进程B中断了, 那么, 当B被挂起, 重新切换回A的时候, 当然要从中断处理程序被中断的点开始运行, 此时, 恢复A, 有什么不对吗?
作者: jiangzj123    时间: 2011-03-25 15:06
本帖最后由 jiangzj123 于 2011-03-25 15:14 编辑
切换到B, B就开始运行了, 也就是中断处理程序被进程B中断了, 那么, 当B被挂起, 重新切换回A的时候,  ...
faku 发表于 2011-03-25 14:44

中断被挂起,谁来保护它的“现场”?,如果没有现场保护,他怎么能回来继续执行呢,如何去恢复A的现场呢?A又怎么能在断点处接着运行呢
作者: 灌水菜鸟    时间: 2011-03-25 16:18
王八的屁股,规定。就像靠右行驶一样,高效省事,呵呵。如果确实想切换也行,中断线程化呗,呵呵,那样就是在进程上下文了,随便睡。
作者: faku    时间: 2011-03-25 20:03
王八的屁股,规定。就像靠右行驶一样,高效省事,呵呵。如果确实想切换也行,中断线程化呗,呵呵,那样就是 ...
灌水菜鸟 发表于 2011-03-25 16:18


这才是正解

__switch_to()宏(好像是这个, 本人现手头上没内核源码), 切换进程时候, 不是有一个把标号1地址压栈的操作吗?
pushl 1f
然后进程就切换走了, 回来的时候, 不是从1那开始执行的吗?

这段代码不是也在时钟中断里吗? 时钟中断发生时, 不是也不能确定哪个进程在运行吗? 为啥能切换回来呢?

所以, 不是不能, 是设计者不愿意这么做而已吧,

以上是我的愚见
作者: faku    时间: 2011-03-25 20:08
中断被挂起,谁来保护它的“现场”?,如果没有现场保护,他怎么能回来继续执行呢,如何去恢复A的现场呢? ...
jiangzj123 发表于 2011-03-25 15:06



  假如, 完全是假如:
假如 硬盘中断来了, 表示有数据要传输, 这时, 时钟中断又来了, 中断了硬盘中断, 时钟中断里调用了schedule();为啥不能保护硬盘中断的现场?
schedule()就是干这个的!
作者: ccl0326    时间: 2011-03-28 11:24
可以嵌套是因为新来的中断会与老中断一起使用前一个进程的内核栈,但是因为中断而造成Context Switch,前一个进程会很冤枉的




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2