优先级抢占式调度
本章的示例程序已经演示了 FreeRTOS 在什么时候以及以什么方式选择一个什么
样的任务来执行。
每个任务都赋予了一个优先级。
每个任务都可以存在于一个或多个状态。
在任何时候都只有一个任务可以处于运行状态。
调度器总是在所有处于就绪态的任务中选择具有最高优先级的任务来执行。
这种类型的调度方案被称为”固定优先级抢占式调度”。所谓”固定优先级”是指每个
任务都被赋予了一个优先级,这个优先级不能被内核本身改变(只能被任务修改)。”抢占
式”是指当任务进入就绪态或是优先级被改变时,如果处于运行态的任务优先级更低,
则该任务总是抢占当前运行的任务。
任务可以在阻塞状态等待一个事件,当事件发生时其将自动回到就绪态。时间事件
发生在某个特定的时刻,比如阻塞超时。时间事件通常用于周期性或超时行为。任务或
中断服务例程往队列发送消息或发送任务一种信号量,都将触发同步事件。同步事件通
常用于触发同步行为,比如某个外围的数据到达了。
通过图示某个应用程序的执行流程展现了抢占式调度的行为方式
如图 图 中所示
1. 空闲任务
空闲任务具有最低优先级,所以每当有更高优先级任务处于就绪态是,空闲任
务就会被抢占 —— 如图中 t3, t5 和 t9 时刻。
2. 任务 3
任务 3 是一个事件驱动任务。其工作在一个相对较低的优先级,但优先级高于
空闲任务。其大部份时间都在阻塞态等待其关心的事件。每当事件发生时其就
从阻塞态转移到就绪态。FreeRTOS 中所有的任务间通信机制(队列,信号量等)
都可以通过这种方式用于发送事件以及让任务解除阻塞。
事件在 t3,t5 以及 t9 至 t12 之间的某个时刻发生。发生在 t3 和 t5 时刻的事件
可以立即被处理,因为这些时刻任务 3 在所有可运行任务中优先级最高。发生
在 t9 至 t12 之间某个时刻的事件不会得到立即处理,需要一直等到 t12 时刻。
因为具有更高优先级的任务 1 和任务 2 尚在运行中,只有到了 t12 时刻,这两
个任务进入阻塞态,使得任务 3 成为具有最高优先级的就绪态任务。
3. 任务 2
任务 2 是一个周期性任务,其优先级高于任务 3 并低于任务 1。根据周期间隔,
任务 2 期望在 t1,t6 和 t9 时刻执行。
在 t6 时刻任务 3 处于运行态,但是任务 2 相对具有更高的优先级,所以会抢占
任务 3,并立即得到执行。任务 2 完成处理后,在 t7 时刻返回阻塞态。同时,
任务 3 得以重新进入运行态,继续完成处理。任务 3 在 t8 时刻进入阻塞状态。
4. 任务 1
任务 1 也是一个事件驱动任务。任务 1 在所有任务中具有最高优先级,因此可
以抢占系统中的任何其它任务。在图中看到,任务 1 的事件只是发生在在 t10
时刻,此时任务 1 抢占了任务 2。只有当任务 1 在 t11 时刻再次进入阻塞态之
后,任务 2 才得以机会继续完成处理。
选择任务优先级
从图 中可以看到优先级分配是如何从根本上影响应用程序行为的。
作为一种通用规则,完成硬实时功能的任务优先级会高于完成软件时功能任务的优
先级。但其它一些因素,比如执行时间和处理器利用率,都必须纳入考虑范围,以保证
应用程序不会超过硬实时的需求限制。
单调速率调度(Rate Monotonic Scheduling, RMS)是一种常用的优先级分配技术。
其根据任务周期性执行的速率来分配一个唯一的优先级。具有最高周期执行频率的任务
赋予高最优先级;具有最低周期执行频率的任务赋予最低优先级。这种优先级分配方式
被证明了可以最大化整个应用程序的可调度性(schedulability),但是运行时间不定以及
并非所有任务都具有周期性,会使得对这种方式的全面计算变得相当复杂。
协作式调度
本书专注于抢占式调度。FreeRTOS 可以选择采用协作式调度。
采用一个纯粹的协作式调度器,只可能在运行态任务进入阻塞态或是运行态任务显
式调用 taskYIELD()时,才会进行上下文切换。任务永远不会被抢占,而具有相同优先
级的任务也不会自动共享处理器时间。协作式调度的这作工作方式虽然比较简单,但可
能会导致系统响应不够快。
实现混合调度方案也是可行的,这需要在中断服务例程中显式地进行上下文切换,
从而允许同步事件产生抢占行为,但时间事件却不行。这样做的结果是得到了一个没有
时间片机制的抢占式系统。或许这正是所期望的,因为获得了效率,并且这也是一种常
用的调度器配置。