一、 代码的临界区
代码临界区指操作系统在处理时不可分割的代码。一旦这部分代码开始执行,则不允许任何中断打扰。为确保临界段代码的执行,在进入临界段之前要关中断,而临界段代码执行完以后要立即开中断。如下关于A/D采样的代码中有这么一段:
- <span style="font-size:14px;">Int main()
- {
- _DINT();
- WDTCTL=WDTPW+WDTHOLD;
- InitClock();
- InitAD12();
- InitTimerA();
- ADValue=0;
- _EINT();
- …
- }</span>
实际上,这段代码中_DINT()关中断和_EINT()开中断所包括的代码就是一个临界区。由于初始化操作需要设置系统时钟、设定定时器等,那么这段代码是不应该被外部中断将其中断执行并更改的。
不同的嵌入式操作系统实现临界区的方式也各不相同,对于uC/OSii,该系统定义了两个宏(macros)来关中断和开中断,以便避开不同C编译器厂商选择不同的方法来处理关中断和开中断。uC/OSii,中的这两个宏调用分别是:OS_ENTER_CRITICAL()和OS_EXIT_CRITIAL().开发者可以根据采用的硬件平台,实现这两个宏。这里只不过做了一个封装。
而嵌入式Linux实现临界区的方法有多种,可以采用自旋锁spin_lock的方法防止多个进程操作同一段临界区。Spin_lock()是一个内核函数,开发者包括文件就可以使用它了。
................................
...............................
二、 未雨绸缪——临界区中断处理 ---为什么Linux 内核里面很多代码为了处理race condition(竞争条件),都加上了诸如cli sti这样的开关中断指令???
......
..................
..........................
三、中断延迟
(Interrupt Latency) 中断延迟
是指从硬件中断发生到开始执行中断处理程序第一条指令之间的这段时间。
也就是:
计算机接收到中断信号到操作系统作出响应,并完成换到转入中断服务程序的时间。
不严格地,也可以表述为:
(外部)硬件(设备)发生中断,到系统执行中断服务子程序(ISR)的第一条指令的时间。
另外,如果尽可能严格地考虑问题,那么还要考虑下列情况:
1.中断的详细情况就是:外界硬件发生了中断后,CPU到中断处理器读取中断向量,并且查找中断向量表,找到对应的中断服务子程序(ISR)的首地址,然后跳转到对应的ISR去做相应处理。此部分时间,我称其为:识别中断时间
2.在允许中断嵌套的实时操作系统中,中断也是基于优先级的,允许高优先级中断抢断正在处理的低优先级中断,如ucOS/II,所以,如果当前正在处理更高优先级的中断,即使此时有低优先级的中断,系统也不会立刻响应,而是等到高优先级的中断处理完之后才会响应。
而即使在不支持中断嵌套,即中断是没有优先级的,中断是不允许被中断的,所以,如果当前系统正在处理一个中断,而此时另一个中断到来了,系统也是不会立即响应的,而只是等处理完当前的中断之后,才会处理后来的中断。此部分时间,我称其为,等待中断打开时间 。
3.在嵌入式系统中,如ucOS/II,(其他类似系统中也有此情况),常用开关中断来实现共享区的互斥访问。 如:
//利用μC/OS_Ⅱ 宏调用关中断和开中断
- void Function (void)
- {
- OS_ENTER_CRITICAL(); //关闭中断
- .
- .
- .
- OS_EXIT_CRITICAL(); //打开中断
- }
所以,会出现这种情况,当前中断来了,但由于之前某个程序访问共享区,而关闭中断了,导致当前中断得不到处理。而只有等待其访问完成共享区之后,再开中断。(不过,一般来说,关中断的时间都很短,否则也就不适合用开关中断的方法来实现共享区互斥访问,而应该用信号量或者其他手段实现。因为关中断时间长短,是衡量一个实时系统性能好坏的一个重要指标)
此部分时间,我称其为:关闭中断时间
4.其他的有待高人补充。
所以,总的中断延迟时间就可以表示为:
中断延迟 = 识别中断时间 + [等待中断打开时间] + [关闭中断时间]
当然,对于2、3两种情况,很多时候,并没有遇到。所以,一般多为中断延迟等于识别中断时间。
注:对于保存所要用到的寄存器内容或称保存现场,保存上下文等,此处也叫 中断前导。并且做相应中断处理。在处理完之后,进行恢复,此处也叫中断后续,这些工作,是在中断处理子程序ISR完成的 。