多任务系统中,内核(Kernel)负责管理任务,或者说为每个任务分配CPU时间,并且负责任务间的通信。内核提供的基本服务是任务切换,实时内核允许将应用分成若干个任务,由实时内核来管理它们。
调度(Schedulers)是内核的主要职责之一,决定轮到哪个任务运行,每个任务根据其重要程度的不同,被赋予一定的优先级。基于优先级的调度法是指,CPU总是让处于就绪态的、优先级最高的任务先运行。然而何时高优先级任务掌握CPU的使用权,由使用的内核类型确定,基于优先级的内核有不可抢占型和可抢占型两种类型。
不可抢占型内核(Non-Preemptive Kernel),要求每个任务主动放弃CPU的使用权。不可抢占型调度法也称为合作型多任务,各个任务彼此合作共享一个CPU。但异步事件还是由中断服务来处理的,中断服务可使高优先级的任务由挂起态变为就绪态,但中断服务以后,使用权还是回到原来被中断了的那个任务,直到该任务主动放弃CPU的使用权为止,新的高优先级的任务才能获得CPU的使用权。
当系统响应时间很重要时,须使用可抢占型内核(Preemptive Kernel)。在可抢占型内核中,一个正在运行的任务可以被打断,而让另一个优先级更高、且变为就绪态的任务运行。如果是中断服务子程序使高优先级的任务进入就绪态,中断完成时,被中断的任务被挂起,优先级高的任务开始运行。MQX属于可抢占型内核,第3章和第5章将详细阐述。
时钟节拍是特定的周期性中断,通过定时器产生周期性的中断供内核判断是否有更高优先级的任务已进入就绪状态。
硬实时(Hard Real-Time)要求在规定的时间内必须完成操作,是在设计操作系统时保证的,通常将具有优先级驱动的、时间确定性的、可抢占调度的RTOS系统称为硬实时系统。软实时(Soft Real-Time)则没有那么严格,只要按照任务的优先级,尽可能快地完成操作即可。
RTOS追求的是调度的实时性、响应时间的可确定性、系统的高度可靠性,评价一个RTOS一般可以从任务调度、内存开销、系统响应时间、中断延迟等几个方面来衡量。
(1)任务调度的时间指标。RTOS的实时性和多任务能力在很大程度上取决于它的任务调度机制。在大多数商用的实时系统中,为了让操作系统能够在有突发事件时,迅速取得系统控制权以便对事件做出反应,所以大都提供了“抢占式任务调度”功能,也就是操作系统有权主动终止应用程序(应用任务)的执行,并且将执行权交给拥有最高优先级的任务。
① 调度延时(Scheduling Latency):指当一个更高优先级的任务就绪到这个任务开始运行之间的时间。简而言之,就是一个任务被触发后,由就绪到开始运行的时间。
② 任务切换时间(Context-Switching Time):由于某种原因使一个任务退出运行时,RTOS保存它的运行现场信息,并插入相应队列,依据一定的调度算法重新选择一个新任务使之投入运行,这一过程所需时间称为任务切换时间。任务切换时间越短,RTOS的性能就越高。
③ 恢复时间(Recovery Time):指从任务完成后,系统响应到恢复执行主程序所需要的时间。
(2)最小内存开销。在RTOS的设计过程中,由于成本限制,嵌入式系统产品内存的配置一般都不大,而在有限的内存空间内不仅要装载RTOS,还要装载用户程序,因此,最小内存开销是一个重要的指标,这是RTOS设计与其他操作系统设计的明显区别之一。
(3)系统响应时间。系统响应时间(System Response Time)是指系统发出处理要求到系统给出应答信号的时间,也就是指从任务请求产生到任务完成之间的时间间隔,需要满足一定的时间约束(临界时间)。控制要满足一定的实时性要求,就是响应时间小于临界时间。
系统响应时间由反应时间和处理时间两个方面组成。对应于计算控制的实时系统,反应时间指外部中断提交到CPU开始处理的时间,处理时间指CPU完成处理的时间。提高系统的响应时间,可以从缩短反应时间和处理时间两个方面入手。反应时间是电信号的传导时间,对于不同速度的处理器,这个时间相差不大。
(4)中断延迟。中断是一种硬件机制,用于通知CPU发生了一个异步事件。CPU一旦识别出一个中断,保存任务上下文后,跳至该中断服务程序ISR执行,处理完这个中断后,返回到就绪队列中具有最高优先级的任务执行。当RTOS运行在核心态或执行某些系统调用时,是不会因为外部中断的到来而立即执行中断服务程序的,只有当RTOS重新回到用户态时才响应外部中断请求,这一过程所需的最大时间就是中断禁止时间。
中断延迟(Interrupt Latency)时间是指系统确认中断开始直到执行中断服务例程第一条指令为止,整个处理过程所需要的时间。中断禁止时间越短,系统的实时性越高。
代码临界段也称为临界区,是指处理时不可分割的代码。一旦这部分代码开始执行,则不允许任何中断打扰。为确保临界段代码的执行,在进入临界段之前要关中断,且临界段代码执行完后应立即开中断。