freeRTOS调度策略
背景
嵌入式的设备开发通常有两种模式:裸机开发和OS开发。像功能较为强大的SOC通常都会先一直linux或其他OS然后进行业务逻辑的开发;而单片机则有很多简单的应用场景直接使用裸机开发的模式,稍微复杂些的场景,会先移植OS,然后在OS的基础上开发。我认为移植OS主要有两大需求:实现多线程和更加方便的资源管理,比如内存管理。多线程的实现离不开调度器,调度器的实现又分不开现场切换和调度策略。不同OS通常会有不同的调度策略,有些大型的OS比如linux甚至于会同时支持多种调度策略。本文简单描述目前比较常见的freeRTOS调度策略。
参考资料
所有内容均参考freeRTOS官网
具体内容
话不多说,先上图
不同于linux或者windows的进程线程概念。freeRTOS中并发的载体被称之为任务。开发者可以基于freeRTOS常见多个任务,从而实现并行运行的需求。比如:现在有个需求:现在需要通过单片机实现一个MP3播放器,该播放器带一个触摸屏,用户需要在播放音乐的同时,还可以通过触摸屏实现人机交互。这样,至少需要两个任务并发运行,一个处理音乐播放功能,一个响应触摸屏的各种功能。
那么,freeRTOS是如何将cpu的资源分配给各个任务的呢?是能者多得,还是一碗水端平?
首先,os会将所有的任务分配一个状态:
运行态(Running):当前正在使用cpu的任务,对于单核cpu来说,同一时刻只有一个任务能被标志为运行态。
阻塞态(blocked):当前任务需要被某一事件触发(等待时间或外部事件),才能参与调度。被触发前任务的状态就为阻塞态。通常,阻塞态的任务会设置超时时间,超时后,任务自动解除阻塞,可以参与调度。特殊情况可以一直阻塞下去。
当调度期发现任务处于阻塞态,就不会选择其进入运行态。
挂起态(suspended):挂起态的任务进入和解挂一般由一组API实现,相对于阻塞态而言,挂起和解挂的时机更具操控性。
当调度期发现任务处于挂起态,就不会选择其进入运行态。
就绪态(Ready):任务非阻塞和挂起,满足任务调度条件,就会被置为就绪态,可以参与调度器的调度。
总结:任务切换主要发生在运行态和就绪态。而就绪态更像是任务可以被调度的入场卷,只有就绪态的任务,才有可能被运行。
调度:针对单核CPU、非对称多核(AMP)CPU、对称多核(SMP)CPU。OS提供了不同的调度策略。
单核(默认):使用固定优先级的抢占式调度策略,对于同等优先级的任务执行时间片轮询策略。
抢占式调度策略:无论任务处于任何时刻(任务切换过程中还是任务运行的时间碎片内),加入调度器发现当前运行的任务不为最高优先级任务,那么调度器就会立马转去调度优先级最高的任务运行。举个例子:假如有个优先级为5的任务(该任务当前优先级最高)正在运行,突然有中断进来,将某原本优先级为4的任务修改优先级为6,那么调度器就会切换当前运行任务为优先级为6的任务。
轮询策略:是指相同优先级的任务轮流进入运行状态。
时间片:时间片为一个定时器实现,定时固定时间长度也就是时间片,调度器安排相同优先级的下一个任务开始运行。
问题:
1.如此说来,在该调度策略之下,加入高优先级的任务既不挂起也不阻塞,那岂不是低优先级的任务从来都不会有被调度的可能?
确实是这样的,那如何避免该问题发生?通常最好创建事件驱动型任务,假如某个高优先级的任务正在等待一个事件,那么就不应该使该任务处于任务轮询(事件片轮询)中,而应该将其设置为阻塞态或者挂起态。从而保证低优先级的任务不会一直处于饥饿状态。
2.中断本身也有优先级,该优先级是否会映射入任务优先级?
AMP调度策略
使用 FreeRTOS 的非对称多处理 (AMP) 是指多核设备的每个核心都单独运行自己的 FreeRTOS 实例。这些 核心并不都需要具有相同架构, 但如果 FreeRTOS 实例之间需要进行通信,则需要共享一些内存。
每个核心都会运行自己的 FreeRTOS 实例, 因此任何给定核心上的调度算法与上文的单核系统调度算法完全相同 。您可以使用流缓冲区或消息缓冲区作为核间通信原语, 这样一来,一个核心上的任务可以进入“阻塞”状态, 以等待另一个核心发来的数据或事件。
FreeRTOS SMP 调度策略
使用 FreeRTOS 的对称多处理 (SMP) 是指 一个 FreeRTOS 实例可以跨多个处理器核心调度 RTOS 任务。由于 只有一个 FreeRTOS 实例在运行,一次只能使用 FreeRTOS 的一个端口, 因此每个核心必须具有相同的处理器架构并共用 相同的内存空间。
FreeRTOS SMP 调度策略使用与单核调度策略相同的算法, 但与单核和 AMP 场景不同的是, SMP 在任何给定时间都会导致多个任务处于运行状态 (每个核心上都有一个运行状态的任务)。这意味着, 只有缺乏可运行的高优先级任务时,才会运行低优先级任务的假设不再成立 。要想了解其中的原因,请考虑一下, 若起初只有一个高优先级任务 和两个中等优先级任务处于 “就绪”状态,SMP 调度器会如何选择在双核微控制器上运行的任务。调度器需要选择两个任务,每个核心对应一个任务。 首先,高优先级任务是指可运行的最高优先级任务, 因此会选择将它用于第一个核心。 这样就剩下了两个中等优先级的任务 作为可运行的最高优先级任务,因此会将它们用于第二个核心 。结果是高优先级和中等优先级的任务同时运行。