前一段时间,有幸和都江堰操作的作者面对面的聊了一把。对于前辈的技术和才能,晚辈深深地佩服。DJY_OS在应用方面的事件机制以及处理中断的方法都让人眼前一亮。在谈到中断时,前辈说,很多人都没有真正的理解中断。于是我就请教了前辈。他说:
“http://www.djyos.com/bbs/forum.php?mod=viewthread&tid=6082&extra=page%3D1
1、  中断是异步事件。
2、  中断不一定是紧急事件。
3、  紧急事件必须用中断来通知。
关键是这三句话。”
 
其实,我听了以后,还是有点迷糊。第一什么是异步事件?Google一下,异步事件是指计算机外部产生的,同计算机内执行的任务在时间上不相关联的事件。(http://define.cnki.net/WebForms/WebDefines.aspx?searchword=%E5%BC%82%E6%AD%A5%E4%BA%8B%E4%BB%B6)

那么这里有个疑问了,软中断是由软件出发的,一般用于呼叫系统服务。这时应用程序必须等待系统服务完成后才能从软中断处继续执行。显然,这种事件不满足这个异步事件的定义,那么它还算是中断吗?也许前辈只是借用了异步事件的术语,指得其它的东西。疑惑促使我去思考这些问题。

中断系统一直困扰着我。我不明白中断和任务最本质的区别。这里先提一下调度,调度的本质是分配CPU的时间。即分配CPU的计算时间给每一个需要计算的任务(线程)。中断发生以后,需要执行中断服务程序(ISR)。ISR显然也有一些任务(线程)的影子。

有一些新CPU,如Cortex-M3之类的,有NVIC,中断控制器。不需要软件做栈的保护(它自己可以做),上电以后初始化栈后,它自己就可以正常工作了。支持背靠背执行ISR。其他处理器上的系统都是执行完了ISR后,再执行一条非ISR指令,防止频繁执行ISR造成前台程序饿死。背靠背的意思是ISR执行完毕后,直接执行另外一个ISR,不执行任何前台代码。这有个好处,没有用户程序的压栈出栈,现场保护。速度快了很多。缺点就是,如果中断很多的话,前台程序得不到执行(不过这个效应应该不明显)。

所有这些,让我想到,中断控制器实际上不就是个带优先级别支持抢占的硬件调度器吗?:),事实的确如此。一个高优先级的ISR不退出的话,低优先级的ISR是得不到服务的。低优先级的ISR在服务时,发生高优先级的ISR,那么直接就被抢占了。我们用关闭中断,实际上就是关闭硬件的调度器。而操作系统(OS),从这个硬件调度器来看,实际上相当于空闲任务(或进程)。当系统没有ISR运行的时候,自然运行空闲任务,也就是操作系统的(OS)。这么一看,这是多么的与抢占式的软件调度器吻合。

硬件只提供了一个抢占式的调度器,并未在此基础上提供丰富的系统调用,诸如信号量、互斥体等等API。而软件调度器是我们真正想要的东西。软件提供了各种各样的同步、通信API。用以管理系统内部的资源。一山容不得二虎,必须有一个主一个从。软件调度器作为我们需要的主流,硬件调度器自然退为二线,默默支持着主调度器。

从硬件调度器的角度去观察,衍生出很多有力的解释:
1.既然硬件调度器被抑制,那么要以主调度器为主。中断ISR应尽可能做最少的事情。尽量不影响主调度器的工作。
2.硬件调度器是个基于优先级的抢占内核,而OS运行在最低优先级。在ISR里不能调用阻塞的函数。调用了,整个系统就崩溃了。或者说发生了优先级反转,但硬件调度器没有提供这个功能。只能是死锁或者是长时间的等待。
3.硬件调度器使用的栈(包括ISR)应该是和操作系统在一个数据空间里。因为硬件调度器高于软件调度器,即软件调度器只能是停止硬件调度器调度,但无法介入这一调度过程。硬件调度器可没有提供诸如MMU切换之类的功能。
4.对于资源的拥有性上来说,操作系统(软件调度器)接管了所有的资源,甚至它把中断也当成了一种资源。对于硬件调度器,它只能拥有最基本的可以使程序运行的资源。即一点点内存+CPU的时间。内存是软件调度器与之分享的,由操作系统全权接管。
...

一点点拙见,大家拍砖。


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

DJYOS作者,罗大哥的指教:

罗大哥  20:38:16
看了,兄弟有独到的见解,但有些观点还是可以商榷的。
Ultra-Apple  20:39:42
指教。
罗大哥  20:39:56
比如软中断,这里的“中断”,指的是swi指令(x86的int指令)的响应过程,有点像中断。
1、会陷入特权级。
2、多数会有独立的栈。
至于背靠背,不仅仅m3,ARMx都是背靠背的。
Ultra-Apple  20:42:03
:)
罗大哥  20:42:47
所以,现在“软中断”这个术语,很多著作上倾向于用“异常”这个术语替代。
Ultra-Apple  20:46:12
:)
罗大哥  20:46:42
另外,吧中断上升到硬调度器的高度,感觉有点牵强
Ultra-Apple  20:48:21

罗大哥  20:49:39
当然,从处理过程上,也确实像调度器。
Ultra-Apple  20:50:55
恩,写得不好,让罗大哥见笑了。
本来想表达的意思是用ARM举例,不仅限于ARM。

--------------------------------------------------------------------------------------文章补遗---------------------------------------------------------------------

又和罗大哥讨论了一下,水平有限,文中的确有一些模棱两可的地方。补充一下,完善本文的观点。
底层程序员观察来看:

1.中断是异步事件;什么时候发生的确依赖于客观世界,无法控制。
2.软中断是软件控制的,是同步事件;大多数文献倾向软中断为异常。
3.除数为0,译码错误,地址错误等等异常,也可看作中断,它们是一类特殊的异常。
4.异常和中断最大的区别是,产生的源不同;服务的对象不同。

从CPU来看:
1.中断是异步事件;
2.软中断也是异步事件, CPU不知道代码什么时候想软中断;
3.其他类的异常也是异步事件。
假设如果用FPGA实现CPU的话,用异步的方式可以统一这些设计。换句话说,虽然概念上区分异常和中断,但在内在实现上是高度相似的。

继续从CPU来看:
1.不可屏蔽中断,是最高优先级中断且不受中断禁止的制约;
2.普通的中断可以配置优先级别;
3.异常分为两类,一类是可屏蔽的;一类是不可屏蔽的。不可屏蔽的异常优先级和不可屏蔽中断有得一拼(应该是有优先级差别的);可屏蔽异常的优先级应该比普通中断低。
4.在以上服务程序都没有工作的时候,运行操作系统。

抽象一下,如果把CPU看成一个类似RTEMS、uCOS-II之类的RTOS的话。实际上ISR也好,异常服务也好,操作系统也好,都是“硬件调度器”的任务。而操作系统是硬件调度器的空闲任务。