我正在阅读Robert Love的以下文章
http://www.linuxjournal.com/article/6916
说的是
"...让我们讨论工作队列在进程上下文中运行的事实.这与其他下半部机制形成对比,后者都在中断上下文中运行.在中断上下文中运行的代码无法休眠或阻塞,因为中断上下文没有重新安排的后台进程.因此,由于中断处理程序与进程没有关联,调度程序没有任何东西可以进入休眠状态,更重要的是,调度程序无需唤醒..."
我不明白.AFAIK,内核中的调度程序是O(1),它是通过位图实现的.那么什么阻止了scehduler将中断上下文置于睡眠状态并采取下一个可调度进程并将其传递给控件?
Kei*_*ith 41
那么什么阻止了scehduler将中断上下文置于睡眠状态并采取下一个可调度进程并将其传递给控件?
问题是中断上下文不是进程,因此无法进入休眠状态.
发生中断时,处理器将寄存器保存到堆栈中并跳转到中断服务程序的开始.这意味着当中断处理程序正在运行时,它正在中断发生时正在执行的进程的上下文中运行.中断正在该进程的堆栈上执行,当中断处理程序完成时,该进程将继续执行.
如果你试图在中断处理程序中睡眠或阻塞,你不仅会停止中断处理程序,还会中断它所中断的进程.这可能很危险,因为中断处理程序无法知道中断进程正在做什么,或者即使该进程被挂起也是安全的.
事情可能出错的一个简单场景是中断处理程序和它中断的进程之间的死锁.
此时,你有一个僵局. 在ISR完成其堆栈之前,Process1无法恢复执行.但ISR被阻止等待Process1释放LockA.
Sam*_*iao 30
我认为这是一个设计理念.
当然,你可以设计一个你可以在中断时睡觉的系统,但除了让系统难以理解和复杂(你需要考虑许多情况),这对任何事都没有帮助.所以从设计的角度来看,声明中断处理程序因为无法入睡而非常清晰且易于实现.
来自Robert Love(内核黑客):http: //permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791
您无法在中断处理程序中睡眠,因为中断没有后备进程上下文,因此没有任何内容可以重新安排回来.换句话说,中断处理程序与任务无关,因此没有"睡觉"和(更重要的是)"无需唤醒".他们必须原子地运行.
这与其他操作系统不同.在大多数操作系统中,中断没有线程化.然而,下半部通常是.
页面错误处理程序可以休眠的原因是它仅由在进程上下文中运行的代码调用.因为内核自己的内存不可分页,所以只有用户空间内存访问才会导致页面错误.因此,只有少数特定位置(例如对copy_ {to,from} _user()的调用)可能导致内核中的页面错误.那些地方都必须由可以睡眠的代码(即,处理上下文,没有锁等)来完成.
因为线程切换基础设施在那时是不可用的.处理中断时,只能执行更高优先级的内容 - 有关中断,任务和处理器优先级,请参阅" 英特尔软件开发人员手册".如果你确实允许另一个线程执行(你在问题中暗示这很容易),你将无法让它做任何事情 - 如果它导致页面错误,你必须使用服务在内核中,在中断服务期间无法使用(请参阅下面的原因).
通常,中断例程中的唯一目标是让设备停止中断并在较低的中断级别排队(在unix中这通常是非中断级别,但对于Windows,它是dispatch,apc或被动级别)在您可以访问kernel/os的更多功能的情况下进行繁重的工作.请参阅 - 实现处理程序.
这是O/S必须如何工作的属性,而不是Linux中固有的东西.中断例程可以在任何时刻执行,因此您中断的状态不一致.如果您中断了线程调度代码,则其状态不一致,因此您无法确定可以"休眠"并切换线程.即使您保护线程切换代码不被中断,线程切换也是O/S的一个非常高级别的功能,如果您保护它所依赖的所有内容,中断就会比其名称隐含的命令更具建议性.
归档时间: |
|
查看次数: |
27908 次 |
最近记录: |