FreeRTOS 任务调度算法
配置
在FreeRTOSConfig.h.文件中,可以通过configUSE_PREEMPTION和configUSE_TIME_SLICING配置调度算法。
configUSE_TICKLESS_IDLE也会影响调度算法,它用来降低系统功耗。
在FreeRTOS中,拥有相同优先级的任务会被交替执行,即Round Robin Scheduling(RR);
在RR调度策略下,一个线程会一直运行。直到:
- 自愿放弃控制权
- 被更高优先级的线程抢占
- 时间片用完
但是RR算法并不能保证同优先级的每个任务执行时间相同
基于时间片的优先级抢占式调度算法 Prioritized Pre-emptive Scheduling with Time Slicing
配置
相关概念:
示例 每个任务有不同优先级
假设有三个任务,Task1/2/3,Task1有最高优先级;Task2是周期任务,优先级中;Task3优先级低。
- t5时刻Task3开始运行
- 当执行到t6时刻,由于Task2周期触发,且优先级比Task3高,所以调度器将CPU控制权交由Task2
- t7时刻,Task2运行完成,控制权交还Task3继续运行
- t9时刻,Task2周期触发,开始运行
- t10时刻,由于Task1优先级最高,此时抢占CPU,控制权交给Task1
- t11时刻,Task1结束,控制权交还Task2,Task2继续运行
- t12时刻,Task2结束,控制权交还Task3
示例 相同优先级的情况
Task1优先级高于Task2,Task2优先级和空闲任务相同
- 正常情况下,由于Task2和Idle优先级相同,所以他们交替执行
- t6时刻,Task1抢占CPU
- t7时刻,任务1释放CPU;由于Task2和Idle是交替执行的,在t5~t8这个时间周期中,Task2开始占用CPU
这个例子展示了空闲任务和普通任务的交替执行过程。但是,如果空闲优先级任务有工作要做,但空闲任务没有工作,则可能不需要为空闲任务分配这么多处理时间。
我们可以对configIDLE_SHOULD_YIELD进行配置。
- configIDLE_SHOULD_YIELD = 1
此时,如果有其他空闲优先级的任务,空闲任务将会让出控制权 - configIDLE_SHOULD_YIELD = 0
此时,除非有高优先级任务抢占发生,否则空闲任务将会保持运行
如图所示:
此时configIDLE_SHOULD_YIELD=1。可以看到,空闲优先级任务有了更多的处理时间。
无时间片的优先级抢占式调度算法 Prioritized Pre-emptive Scheduling (without Time Slicing)
算法保留了调度算法,但是没有用到时间片来处理相同优先级的任务。
配置
示例
不使用时间片会使得更少的上下文切换,因此,这样会减小调度器的负载。但是,这样也会导致相同优先级任务的处理时间不同。如下图所示,
由于没有使用时间片,空闲任务会一直占有CPU,直到Task1抢占CPU结束后,Task2才有机会运行。
合作调度 Co-operative Scheduling
配置
当使用合作调度模式时,上下文的切换只发生在
- 正在运行的任务进入阻塞态
- 任务调用askYIELD()退出
如图所示:
示例
在多任务应用时,如果某个资源一次只能被一个任务访问,否则将会导致程序出错。那么,需要用到这个方式。
比如说,当有两个任务需要通过串口输出,如果允许抢占,那么会导致两个任务冲突。