关于中断的一点点认识

来源:互联网 发布:中国直播网络灵异事件 编辑:程序博客网 时间:2024/05/17 01:37
前一段时间,有幸和都江堰操作的作者面对面的聊了一把。对于前辈的技术和才能,晚辈深深地佩服。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也好,异常服务也好,操作系统也好,都是“硬件调度器”的任务。而操作系统是硬件调度器的空闲任务。

********************************************************************************************************
djyos的中断实时性
使用RTOS的场合,大多都对实时性有要求,甚至有些要求极端高的实时性。一般来说,设计者会把实时性要求很高的部分功能,用中断来实现,从这个意义上,对于RTOS来说,最坏情况下的中断响应延迟,几乎就是该系统的实时性指标。现有操作系统,或多或少的会带来额外的、不确定的中断延时,使许多实时性要求很高的应用,要么不使用操作系统,要么需要增加额外的硬件来处理实时任务。djyos在最坏情况下,提供近乎裸跑的中断延迟,实现无以伦比的实时性,使得一些原来只能裸跑的应用,也可以使用操作系统。
由于中断实时性在RTOS中极端重要,本文以中断为重点,谈谈实时性。
1.     理解中断
代码,是现实问题的一个抽象,同样,设计中断系统,就要先弄清楚“什么是中断,该如何抽象”这个问题。
中断,从形式上看,是一个异步到达的(通知)事件,异步是什么意思呢?异步是相对于主程序的,即主程序不知道什么时候会来中断,也不知道中断达到时,自己运行到什么地方、处于什么状态。中断从形式上,并没有告诉我们,它是否需要处理,更没有说是否需要紧急处理。因此,把中断都看做要“需要紧急处理的事件”,是没有依据的。
由于cpu是串行执行指令的,如果靠cpu执行指令的方式查询获得事件,比如查询IO口获得上升沿事件。从事件发生到cpu查询到的延迟时间,必然跟cpu的查询周期相关,除非你的系统只有“查询并处理中断”这一件任务,否则很难做到很短。因此,紧急事件只能通过中断来获取。
所以,中断可以用三句话来概括:
1、  中断是异步事件。
2、  中断不一定是紧急事件。
3、  紧急事件必须用中断来通知。
了解了中断的三个特性,我们就知道,并不是所有中断,都需要极速响应的,事实上,绝大多数情况下,只有极少量的中断需要很高实时性的。
凡是中断就要求极速响应吗?
答案显然是否定的。许多操作系统对中断的处理,是一视同仁的,而且都把中断看成是一个需要紧急处理的事件,这显然是一个自以为是的想法,根本不知道用户需要什么,也没有理解什么是“中断”。
在操作系统支持下,需要接近裸跑的中断延迟吗?
答案显然是肯定的,但是,人们对此似乎很宽容。为什么会宽容呢?当没有汽车时,人们能够容忍马车的速度;没有火车时,人们容忍汽车的速度;没有飞机时,人们容忍火车的速度。当所有操作系统都做不到近乎裸奔的中断延迟时,人们便容忍OS给中断响应带来额外延迟。
为什么要为一些不紧急的事件(例如键盘)分配中断号呢?
设计者经常为键盘分配中断号,对于台式PC来说,键盘也许勉强算紧急事件,因为PC中有很多慢速操作;但对于使用RTOS的嵌入式控制系统来说,却并非紧急事件。为什么呢?因为键盘是人手通过机械按钮实现的,操作系统的反映,只要比人的动作快就可以了,响应太快了,反而可能导致误触发,失去按键防抖功能。那为什么不少人会把按键挂在中断线上,使用中断来响应按键操作呢?答案是,一可以简化软件设计,不需要单独启动一个键盘扫描线程;二可以减轻cpu负担,不用定期扫描键盘;三是低功耗系统特有的,可以用键盘中断来唤醒休眠的cpu
2.     设计中断系统
理解了中断,我们就可以着手设计中断系统了。
1、              能够为异步事件提供服务,既然是事件,就应该提供普通事件一样的操作系统服务,使其编码更加容易。
2、              为实时中断提供裸跑的中断延迟,即使在最坏情况下,也不能例外。
3、              用户用中断处理异步事件,是希望简化系统设计,因此,不能因为异步事件而使调度系统更加复杂。
传统操作系统,因为没有弄清楚这些问题,企图对所有中断极速响应,又企图给中断响应函数以尽可能多的服务,而两者,却是矛盾的,更多的服务,必然需要更多的关中断,导致中断延迟加长。最终的结果是:
1、  异步事件得不到操作系统的充分支持,对编写ISR程序有诸多限制。
2、  真正实时性要求很高的中断,又做不到很快响应。
3、  调度器保护临界资源时,分为关调度和关中断两级,使系统更加复杂,完全违背了用户的用中断响应异步事件的目的。
Djyos的中断系统,可以用这张图来表示:
一般cpu的中断控制器,都有许多中断输入线,每个中断线对应一个中断号,由一个独立的开关控制。
每个中断线,都允许独立设置为实时中断还是异步信号,该开关可能是硬件开关,也可能是软件开关,依赖于具体硬件以及移植者的选择。
异步信号有一个独立的总使能开关,也就意味着,异步信号是可以整体关断的。
实时中断没有独立的使能开关,意味着,实时中断是不允许集体关断的。
异步信号和实时中断有一个公共的总使能开关,意味着,允许用户关闭所有中断。
Djyos中,“异步信号使能开关”同时又是关调度开关,djyos没有独立的调度开关,使得djyos的临界区保护代码更加简洁,和用户希望通过“用中断实现异步信号”来简化软件设计的目的,是相适应的。简洁的调度器,也是djyos更加可靠。由于关异步信号和关中断等同,使得异步信号处理函数可以使用操作系统提供的全部服务,更加方便易用。
操作系统运行过程中,总中断使能开关时从来不会被关闭的,所以,djyos的实时中断,达到裸跑的速度,这是架构决定的,跟中断响应的代码是否精简无关。
虽然知道中断实时性对RTOS极其重要,但许多RTOS,由于不能对中断做正确的抽象,不能从架构角度提高实时性,往往爱使用一些很复杂的技巧来提高性能。但过多的技巧,实现高性能的同时,可能带来不稳定因素。殊不知,对于实时控制系统来说,稳定性可靠性才是核心。而且,即使再巧妙的技巧,都不能对实时性的提高,带来质的变化。
3.     Djyos中断系统的特点
1、  实时中断具有裸跑的实时性,使得有些原本不能使用操作系统的应用,可以享受操作系统的服务。
2、  编写异步信号编程更加方便,像普通事件一样,允许使用所有操作系统服务。
3、  系统更加简洁可靠,与用户“用中断实现异步信号以简化软件”的目标相一致。

0 0
原创粉丝点击