Chinaunix首页 | 论坛 | 博客
  • 博客访问: 335556
  • 博文数量: 102
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 1146
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-21 22:33
文章分类

全部博文(102)

文章存档

2011年(8)

2010年(94)

我的朋友

分类: LINUX

2010-01-24 23:22:09

一篇关于异常与中断及进程调度的讨论  

这篇文章与我讨论的wheelz网友,是个非常非常Nice的朋友,呵呵



(enthusiast)
09-07-24 11:16
 异常能睡,中断睡不得?

还是有点儿晕了,虽然这是(一个被回答了无数次的问题) 

page fault handler里可以有进程切换,中断里不能有. 

中断睡不下去 ,不是睡下去切不回来,最关键的临界点在哪儿? 


--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主

版主
(Carpal Tunnel)
09-07-24 11:53
 Re: 异常能睡,中断睡不得? 新 []

因为用户态page fault导致的异常是有进程上下文的,也就是说,其实是代表该进程进入异常,因此是可以睡眠的。 

关键点是在于是否有确定的,所代表的进程上下文。有就可以睡眠。 


--------------------

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(enthusiast)
09-07-24 14:08
 Re: 异常能睡,中断睡不得? 新 []

谢谢wheelz回复 

”关键点是在于是否有确定的,所代表的进程上下文。有就可以睡眠。“ 
==== 
你的答复我是认同的。关于中断睡眠这部分,我看ulk的解释与网上流传的有些矛盾之处,比如中断与当前进程什么关系,是在当前进程的上下文里,还是跟当前进程无关,处在中断上下文等 

ulk在讲处理中断时,有 2个步骤 
1. 保存当前进程的环境 --->这个保存与进程切换时的保存一样的,对吧 
2. 准备执行中断的环境 ----> 我理解这个环境应该比较简略 

这样就会jump到interrupt handler去执行。而在此过程中,假如有sleep,要执行进程切换了,而这个时候,是“没有代表进程上下文的”, 
而是处在中断的环境里. 我这么理解“中断环境不是确定的上下文环境”你说对么? 

那么此时又有两个问题: 
1) 因为中断环境无法执行进程切换么 
2) 还是当前进程在切换后就无法被重新调度到? 

这个地方是我不太明白的。由于在进入中断之前已经保存了当前进程的执行环境,那么现在可以用来进程切换呀。。。如果这个切换过程中再保存当前中断的执行环境(不光是进入中断的执行环境,还包括当前的执行点等),那么再切换到此进程时,就可以依据stack的状态信息依次恢复了。。。 

这是我的理解,我想可能还有两个问题 
1) 从硬件观点,确实在中断里不能进程切换 
2) kernel设计角度,因中断的特性不允许进程切换 

谢谢 

附 
1) ulk charpter 4 中断与异常 
2) 一篇与ulk矛盾的文章: http://blog.chinaunix.net/u3/93613/showart_1907687.html 




--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(enthusiast)
09-07-24 16:20
 Re: 异常能睡,中断睡不得? 新 []

同事推荐了篇帖子,写得不错,基本上回答了“中断里不能睡眠”的问题。但”异常里可以睡眠 “,这个问题我还是不太懂。 
相信再研究一段时间,中断异常的不同机制明白了,就懂了。 

帖子地址  

原帖子问题及回答: 
中文是我的注释 

On Tue, 2003-07-01 at 09:22, Martin Maletinsky wrote: 

> I know, that you are not allowed to sleep in an interrupt handler. 
> How ever I am interested to understand the reason(s) for that. Was 
> this a design decision (e.g. to simplify things) for the Linux 
> kernel, or is there a fundamental reason that makes sleeping 
> interrupt handlers simply impossible? (是kernel design还是其它“根本”的原因) 
What about the page fault 
> handler - it (probably) sleeps when it has to swap in a page, 
> why is it possible to sleep for the page fault handler and not for 
> an interrupt handler? 

You cannot sleep in an interrupt handler because interrupts do not have 
a backing process context(我对这个backing process context的理解是,在由进程切换到中断环境时,已经保存的进程上下文环境与当前的中断环境相比,前者是可以满足进程切换的条件的,而后者不可以。中断的环境,姑且称之为中断上下文吧,相对进程上下文比较light,仅仅是些寄存器或其它环境变量,所以调度器无法在离开此种环境后再切换回来), and thus there is nothing to reschedule back 
into. In other words, interrupt handlers are not associated with a task, 
so there is nothing to "put to sleep" and (more importantly) "nothing to 
wake up". They must run atomically.(上面这两句,就是我在之前帖子里提到的“睡不下去”和“醒不来”的问题了。当前的环境(中断环境--A),是由进程上下文--B--里被打断而形成的. A 类似于运行在B之上,而B又不是一个task,调度器无法识别之,要进行sleep进程切换时,nothing to put sleep。另外就是wake_up了。去唤醒谁呢?就算是从当前的A里切换出去了,调度器重新切换回来时,已经找不到A这种环境了。我在上面帖子里同样提到这个问题,找不到A可以找到B啊,为什么不稍做这样的处理,在A要sleep时,把A的环境同样也保存了,以进程B为代表去切换。实际上这样也有问题,原帖子举例说明了,比如spin lock,wait-queue等.总之,这是一个"费力不讨好"的事情。从kernel design的角度,这样做意义不大,麻烦不少) 

This is not unlike other operating systems. In most operating systems, 
interrupts are not threaded. Bottom halves often are, however. 

The reason the page fault handler can sleep is that it is invoked only 
by code that is running in process context. Because the kernel's own 
memory is not pagable, only user-space memory accesses can result in a 
page fault. Thus, only a few certain places (such as calls to 
copy_{to,from}_user()) can cause a page fault within the kernel. Those 
places must all be made by code that can sleep (i.e., process context, 
no locks, et cetera). 

这一段回复,需要再进一步研究。 

Hope this helped. 

Robert Love 
大家可以查看原贴,查看其它回复 

另外,最近kernel新增了中断线程化(interurpt thread),不知道跟这个 有没有关系呢? 




--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(enthusiast)
09-07-24 16:30
 Re: 异常能睡,中断睡不得? 新 []

因为用户态page fault导致的异常是有进程上下文的,也就是说,其实是代表该进程进入异常,因此是可以睡眠的。 
========== 
wheelz,想就这个问题再讨论下 :-) 

1)中断与异常都是从table里找到相应handler的地址,然后跳过去执行,对么? 
2) 异常的不同在于,此过程中它是有进程上下文的,这个我就觉得有点迷糊了。中间的细节是什么呢 
3) 如果异常处理函数,代表着一个进程来运行(类似于函数调用中的状态),那么完成进程切换是可以理解的 

如果3)假设成立,即exception handler stands for function call,那么可以这么理解异常处理函数: 
CPU指令集会在执行指令时查询是否有异常发生,有的话即去table中找到handler地址执行。这期间要做的事情,是什么呢? 
这些事情决定了,异常最终是处在“进程上下文”里. 

3x 



--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(member)
09-07-24 17:20
 Re: 异常能睡,中断睡不得? 新 []

>2) 异常的不同在于,此过程中它是有进程上下文的,这个我就觉得有点迷糊了。中间的细节 
>是什么呢 

异常是同步的,中断是异步的. 

比如fetch/excute instruction, 发生了exception, 会立即进入对应的异常处理程序来处理,处理完 
成后继续运行。这个exception是代表着current来运行的,所以说他是有上下文的。 

中断则允许延期处理,cpu在适合的适合才会处理irq request.

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主

版主
(Carpal Tunnel)
09-07-24 17:24
 Re: 异常能睡,中断睡不得? 新 []

中断肯定是发生在某个进程的上下文中(肯定有一个current), 
但是中断处理函数和这个进程是没有关系的, 
中断处理函数本身是没有什么进程上下文的,最多可以说这是一个中断上下文, 
而内核调度的单元是进程/线程,这个中断上下文是不能参与调度的。 
当然,如果把中断上下文也做成进程上下文,那么中断也就可以参与调度了。 
现在FreeBSD好像就是这样做的,FreeBSD中,对于大部分中断,发生的时候, 
会找一个专门的线程来运行中断处理函数,因此,大部分中断都是以线程身份运行,因此是可以sleep的。 


》那么此时又有两个问题: 
》1) 因为中断环境无法执行进程切换么 
》2) 还是当前进程在切换后就无法被重新调度到? 


中断环境可以切换进程,比如退出中断的时候,是可以进行进程调度的。 
但是中断本身是不能sleep的,也就是说,中断本身在运行到一半的时候,不能去睡眠,然后过一段时间再回来接着运行中断处理函数的后面一半 

也就是说,中断本身,和中断“打断的某个进程”是两个东西。 

page fault异常就不一样了,page fault handler和他打断的进程是紧密关联的。 

事实上,内核的page fault hander并不是整个函数任意地方都可以sleep,因为page fault hander的某些代码并不是处理用户态的进程的page fault的, 
内核也有page fault,这些地方就不能睡眠。 



--------------------

编辑者: wheelz (09-07-24 17:28)

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(enthusiast)
09-07-24 18:16
 Re: 异常能睡,中断睡不得? 新 []

恩 谢谢回复 

这个exception是代表着current来运行的,所以说他是有上下文的。 
===== 
比较中断和异常在”保存当前进程环境状态“与”准备自己运行的环境状态”,并没有实质性的差异吧。 
中断是异步,并不确定打断了哪个进程;而异常一般由于当前进程触发,故与当前进程紧密相关. 
姑且称中断和异常在当前进程环境被保存及自身环境状态准备妥当后的运行环境称为 “中断/异常上下文“。 
正如下面帖子里wheelz所言,在中断上下文里,真要是把此环境抽象成task context,也可以调度,但从kernel design 
的角度,这并非一个好的实现。 
而异常上下文与当前进程关系紧密,故认为其在当前进程的上下文里. 
比如用户态进程A触发异常,需要切换到内核态执行某个异常处理函数。那么此过程中实现的异常上下文就认为是A的一部分,是A 
进程切换到了内核去调用一个函数而已. 不知道这个比喻恰当否 ? 

关键的地方即,异常与当前进程相关,所以把异常处理的环境与当前进程执行环境整合; 
中断是打断当前进程做一件不相关的事情,所以最终没有像异常一样跟当前进程整合,而是把其执行环境特殊自理,这才是纯正的 
中断上下文,与用户态,内核态并列. 




--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主


(enthusiast)
09-07-24 18:34
 Re: 异常能睡,中断睡不得? 新 []

谢谢你的耐心回复 

我认为只要分清”中断处理函数和这个进程是没有关系“的,异常刚相反, 从这个角度思考kernel design问题,”异常能睡,中断睡不得?“就比较好回答了,你说呢 ? (如果这个角度没错的话,呵呵) 




--------------------
一杯绿茶,一颗香烟

文章选项: 打印   将这篇文章放置于备忘录中,待有空时回覆   好友分享   通知版主

版主
(Carpal Tunnel)
09-07-25 18:49
 Re: 异常能睡,中断睡不得? 新 []

基本上是这样。 


所谓的“中断不能睡”,是中断本身的代码中不能睡。 
因为它没有可以参与调度的上下文(或者说数据结构)。 

但似乎怎么说都不是很全面。 
这个问题有些需要意会的地方,还需要结合一下具体的实现。 





--------------------




阅读(1060) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~