3.7 任务调度
任务调度规则:
- 高优先级任务未执行完,低优先级任务无法执行
- 一旦高优先级任务就绪,马上运行
- 同等优先级的任务轮流运行
任务调度是利用链表来管理的,在STM32F103Z中,最高任务优先级configMAX_PRIORITIES=56,即有56个数组pxReadyTasksLists,里面每一个元素都是一个链表,其定义为:
PRIVILEGED_DATA static List_t pxReadyTasksLists[configMAX_PRIORITIES] = {0};
里面存放的是特定优先级的 处于ready或running的 任务
- 启动调度器时,在对应优先级的数组中,会创建由几个任务组成的链表。同时在pxReadyTasksLists[0]下会创建一个空闲任务
- 会有一个全局指针pxCurrentTCB,指向最后创建的任务(因此最后创建的任务会先执行)
- 每过一次时钟中断tick,启动一次任务调度。pxCurrentTCB遍历pxReadyTasksLists,找到第一个非空的list,再在list里面从头遍历
- 当有任务进入阻塞态时,会把他从pxReadyTasksLists中删除,放到xDelayedTaskList中
- 下一次tick开始时,先到xDelayedTaskList看里面的任务是否能被唤醒。若被阻塞的任务能被唤醒,则回到pxReadyTasksLists,然后发起一次调度。
- 当有任务被挂起时,会把他放到xSuspendTaskList中,此时他就不能像被阻塞的任务一样被自动唤醒了。当他被Resume时,则又放回到pxReadyTasksLists中
简而言之,在每一次tick中断中,都会依次做这三件事:
- cnt++
- 判断xDelayedTaskList里面的任务是否可恢复,如果可以恢复,则放到pxReadyTasksLists
- 发起任务调度
由此可以引出编程的良好习惯:
- 以事件驱动任务
- 用vTaskDelay()而不是mdeley()