引 言:
1、系统中断与时钟节拍
1.1 系统中断
中断是一种硬件机制,用于通知cpu有个异步事件发生了。中断一旦被系统识别,cpu则保存部分(或全部)现场(context),即部分(或全部)寄存器的值,跳转到专门的子程序,称为中断服务子程序(isr)。中断服务子程序做事件处理,处理完成后执行任务调度,程序回到就绪态优先级最高的任务开始运行(对于可剥夺型内核)。
中断使得cpu可以在事件发生时才予以处理,而不必让微处理器连续不断地查询(polling)是否有事件发生。通过两条特殊指令:关中断(disable interrupt)和开中断(enable interrupt)可以让微处理器不响应或响应中断。在实时环境中,关中断的时间应尽量的短,关中断影响中断响应时间,关中断时间太长可能会引起中断丢失。中断服务的处理时间应该尽可能的短,中断服务所做的事情应该尽可能的少,应把大部分工作留给任务去做。
1.2 系统时钟节拍
时钟节拍是特定的周期性中断(时钟中断),这个中断可以看作是系统心脏的脉动。操作系统通过时钟中断来确定时间间隔,实现时间的延时及确定任务超时。中断之间的时间间隔取决于不同的应用,一般在10~200 ms之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时提供等待超时的依据。时钟节拍频率越快,系统的额外开销就越大。系统定义了32位无符号整数ostime来记录系统启动后时钟滴答的数目。用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用osstart()之后。μc/osii中的时钟节拍服务是通过在中断服务子程序中调用ostimetick()实现的。时钟节拍中断服务子程序的示意代码如下:
void ostickisr(void) {
保存处理器寄存器的值;
调用osintenter ()或是将osintnesting加1;
调用ostimetick ();
调用osintexit ();
恢复处理器寄存器的值;
执行中断返回指令;
}
2、时钟管理系统
2.1 μc/osii时钟管理系统
μc/osii原有的时钟管理系统类似于linux,但是比linux简单得多。它仅向用户提供一个周期性的信号ostime,时钟频率可以设置在10~100 hz,时钟硬件周期性地向cpu发出时钟中断,系统周期性响应时钟中断,每次时钟中断到来时,中断处理程序更新一个全局变量ostime。μc/osii时钟中断服务程序的核心是调用ostimetick ()函数。ostimetick ()函数用来判断延时任务是否延时结束从而将其置于就绪态。其程序伪代码如下:
void ostimetick(void) {
ostimetickhook();// 调用用户定义的时钟节拍外连函数
while { (除空闲任务外的所有任务)
os_enter_critical();//关中断
对所有任务的延时时间递减;
扫描时间到期的任务,并且唤醒该任务;
os_exit_critical();//开中断
指针指向下一个任务;
}
ostime++;//累计从开机以来的时间
}
在μc/osii的时钟节拍函数中,需要执行用户定义的时钟节拍外连函数ostimetickhook (),以及对任务链表进行扫描并且递减任务的延时。这样就造成了时钟节拍函数ostimetick ()有两点不
足:
① 在时钟中断中处理额外的任务ostimeiickhook (),这样增加了中断处理的负担,影响了定时服务的准确性;
② 在关中断情况下扫描任务链表,任务越多所需要时间越长,而长时间关中断对中断响应有不利影响,是中断处理应当避免的。
2.2 改进的时钟管理系统
针对上述ostimetick ()的不足之处,需加以改进来优化时钟节拍函数。在linux中一般对中断的响应分为两部分:立即中断服务和底半中断处理(bottom half)。立即中断服务仅仅做重要的并且能快速完成的工作,而把不太重要的需要较长时间完成的工作放在底半处理部分来完成,这样就可以提高中断响应速度。