目录
在抢占式的FREE RT OS中,调度器如何选择它需要执行的任务?
xTaskIncreamentTick(void) tick中断的回调函数。
目前实时操作系统(RTOS)多数为抢占式的系统。
#define configUSE_PREEMPTION 1
Free RT OS使用抢占式的任务调度,高优先级的任务抢占低优先级的任务执行。
Free rt os 会根据创建任务的优先级建立多个优先级就绪链表。再创建两个个阻塞链表,一个挂起链表。
就绪链表数组。
阻塞链表
PRIVILEGED_DATA static List_t xDelayedTaskList1 = {0}; //延时的任务
PRIVILEGED_DATA static List_t xDelayedTaskList2 = {0}; 用于超出当前tick计数的延迟。
挂起链表
默认是0-31个优先级,优先级数字越大则优先级等级越高(这与中断嵌套的优先级数字越大则优先级越小)相反。
创建任务后,该任务会根据优先级放在不同的就就绪链表中。
任务可以主动阻塞。在阻塞后,该任务的会从就绪列表中移除并放入阻塞列表中,比如常见的阻塞API函数 OS_Delay(),它会等待tick中断唤醒。唤醒后再次加入它所在优先级的链表中。
从高优先级的任务链表中向链表的尾部遍历,若该高优先级链表没有就绪状态的任务,则向下,向低优先级的链表遍历。
----------------------------------------> 高优先级链表(同一优先级的任务)先向尾部遍历。
| (再向下遍历)
|
|
|
|
|
v
在同等优先级的情况下,若该任务的优先级大于0则后创建的任务会先执行。
创建任务的顺序 :任务1->任务2->任务3
执行顺序 :任务3->任务1->任务2
若该优先级的任务和空闲任务IDLE的优先级相同(也就是为0),则按创建任务的顺序执行。
( 创建任务的顺序和执行任务的顺序相同) 空闲任务(IDLE空闲任务会主动礼让给其他任务)->任务1->任务2->任务3 。(每个任务执行完毕则又插到链表尾部如此往复)。
见源码
如果通过宏配置不抢占也不礼让,无论是否是同优先级,那么永远只有当前任务能一直执行。
/* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */
翻译:
每次tick中断发生时由移植层调用。增加tick值,然后检查新的tick值是否会引起任何变化要解除阻塞的任务。
在xTaskIncreamentTick(void)中
只有配置了可抢占才会发生任务的调度。
在所有任务的优先级相同时,只有配置了可抢占,且配置了使用同优先级下采用时间片轮转的方法,才会使各个任务交替轮流执行一段时间。
比如释放一个信号量
static portBASE_TYPE xHigherPriorityTaskWoken; //发送信号量后切换任务的标记
在中断嵌套中调用
xSemaphoreGiveFromISR(myBinarySem01Handle,&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
通过查看xHigherPriorityTaskWoken的值来判断是否立刻进行任务切换。(PdTRUE立刻切换,否则不切换)
如果最后不调用 portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 则会在下一次调度时被切换。