freertos学习之路3-freertos的任务调度

写在最前

由于工作需要,需要开始学习freertos的相关知识,本专题主要记录freertos的相关内容

参考:

https://www.bilibili.com/video/BV19g411p7UT 正点原子视频

1. 单任务和多任务系统

1.1 单任务系统

任务系统的编程方式,即裸机的编程方式,这种编程方式的框架一般都是在 main()函数
中使用一个大循环,在循环中顺序地调用相应的函数以处理相应的事务,这个大循环的部分可
以视为应用程序的后台, 而应用程序的前台,则是各种中断的中断服务函数。因此单任务系统
也叫做前后台系统,前后台系统的运行示意图, 如下图所示:

freertos学习之路3-freertos的任务调度_第1张图片

从上图可以看出,前后台系统的实时性很差,因为大循环中函数处理的事务没有优先级之
分, 必须是顺序地被执行处理的,不论待处理事务的紧急程度有多高,没轮到只能等着,虽然
中断能够处理一些紧急的事务,但是在一些大型的嵌入式应用中,这样的单任务系统就会显得
力不从心。

1.2 多任务系统

多任务系统在处理事务的实时性上比单任务系统要好得多,从宏观上来看,多任务系统的
多个任务是可以“同时” 运行的,因此紧急的事务就可以无需等待 CPU 处理完其他事务,在被
处理。
要注意的是多任务系统的多个任务可以“同时” 运行,是从宏观的角度而言的,对于单核
的 CPU 而言, CPU 在同一时刻只能够处理一个任务,但是多任务系统的任务调度器会根据相
关的任务调度算法,将 CPU 的使用权分配给任务,在任务获取 CPU 使用权之后的极短时间(宏
观角度)后,任务调度器又会将 CPU 的使用权分配给其他任务,如此往复,在宏观的角度看来,
就像是多个任务同时运行了一样。
多任务系统的运行示意图,如下图所示:

freertos学习之路3-freertos的任务调度_第2张图片

从上图可以看出, 相较于单任务系统而言,多任务系统的任务也是具有优先级的,高优先
级的任务可以像中断的抢占一样,抢占低优先级任务的 CPU 使用权;优先级相同的任务则各自
轮流运行一段极短的时间(宏观角度),从而产生“同时”运行的错觉。 以上就是抢占式调度和
时间片调度的基本原理。
在任务有了优先级的多任务系统中,用户就可以将紧急的事务放在优先级高的任务中进行
处理,那么整个系统的实时性就会大大地提高。

2. 任务调度状态

2.1 四种调度状态

freertos学习之路3-freertos的任务调度_第3张图片

如上图,freertos总共有4种状态

  • 运行态:正在执行的任务,该任务就处于运行态,注意在STM32中,同一时间仅一个任务处于运行态

  • 就绪态:如果该任务已经能够被执行,但当前还未被执行,那么该任务处于就绪态

  • 阻塞态:如果一个任务因延时或等待外部事件发生,那么这个任务就处于阻塞态

  • 挂起态:类似暂停,调用函数 vTaskSuspend() 进入挂起态,需要调用解挂函数vTaskResume()

    才可以进入就绪态

仔细看上图我们可以发现:

  • 只有就绪态可以转变成运行态,其他任务的状态想运行,必须先变成就绪态
  • 其中就绪台挂起态,运行态就绪态可以相互转换

ps:讲到这,我发现这和书本上讲的操作系统的进程这个概念非常像,状态也非常像,如下图,RTOS的任务就类似于我们学的进程吧

freertos学习之路3-freertos的任务调度_第4张图片

2.2 状态转换

  • 创建任务→就绪态(Ready):任务创建完成后进入就绪态,表明任务已准备就绪,随时可以运行,只等待调度器进行调度。

  • 就绪态→运行态(Running):发生任务切换时,就绪列表中最高优先级的任务被执行,从而进入运行态。

  • 运行态→就绪态:有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪列表中,等待最高优先级的任务运行完毕继续运行原来的任务。

  • 运行态→阻塞态(Blocked):**正在运行的任务发生阻塞(挂起、延时、读信号量等待)**时,该任务会从就绪列表中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪列表中当前最高优先级任务。

  • 阻塞态→就绪态阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪列表,从而由阻塞态变成就绪态;如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

  • 就绪态、阻塞态、运行态→挂起态(Suspended):任务可以通过调用vTaskSuspend() API 函数都可以将处于任何状态的任务挂起,被挂起的任务得不到CPU的使用权,也不会参与调度,除非它从挂起态中解除。

  • 挂起态→就绪态:把 一 个 挂 起 状态 的 任 务 恢复的 唯 一 途 径 就 是 调 用 vTaskResume() 或vTaskResumeFromISR() API 函数,如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

2.3 任务状态列表

FreeRTOS中无非就四种状态,运行态就绪态阻塞态挂起态

这四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表

freertos学习之路3-freertos的任务调度_第5张图片

每个列表都是一个32位的变量,当某个位置1时,代表所对应的优先级就绪列表有任务存在

2.4 任务状态例子

不同优先级

假设我们创建了三个任务分别为task1, task2, task3,优先级分别为1,2,3
freertos学习之路3-freertos的任务调度_第6张图片

此时就绪列表中task3放在最前,task2,task1紧随其后

调度器总是在所有处于就绪列表的任务中,选择具有最高优先级的任务来执行

相同优先级

假设我们创建了三个任务分别为task1, task2, task3,优先级都为3

freertos学习之路3-freertos的任务调度_第7张图片

此时task1, task2, task3按照时间片轮流执行

3. 任务调度方式(算法)

和进程调度算法一样,freertos也有任务调度算法

3.1 调度器

FreeRTOS中提供的任务调度器是基于优先级的抢占式调度:在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的。

调度器就是使用相关的调度算法来决定当前需要执行的任务。所有的调度器有一些共同的特性:

  • 调度器可以区分就绪态任务和挂起态任务(由于延迟,信号量等待,事件组等待等原因而使得任务被挂起)。
  • 调度器可以选择就绪态中的一个任务,然后激活它(通过执行这个任务)。 当前正在执行的任务是运行态的任务。

freertos提供三种调度方式:

  • 抢占式调度:主要是针对优先级不同的任务,每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务。
  • 时间片调度:主要针对优先级相同的任务,当多个任务的优先级相同时, 任务调度器会在每一次系统时钟节拍到的时候切换任务。
  • 协程式调度:当前执行任务将会一直运行,同时高优先级的任务不会抢占低优先级任务FreeRTOS现在虽然还支持,但是官方已经表示不再更新协程式调度,由于这种方式就类似于裸机的任务调度方式了,实时性较差,因此这种方式被舍弃

3.2 抢占式调度

我们通过一个例子来讲解抢占式调度的原理,如下图:

freertos学习之路3-freertos的任务调度_第8张图片

运行前提:

  1. 创建三个任务:Task1Task2Task3
  2. Task1Task2Task3的优先级分别为1、2、3;在FreeRTOS中任务设置的数值越大,优先级越高,所以Task3的优先级最高

运行过程

  1. 首先Task1在运行中,在这个过程中Task2就绪了,在抢占式调度器的作用下Task2会抢占Task1的运行
  2. Task2运行过程中,Task3就绪了,在抢占式调度器的作用下Task3会抢占Task2的运行
  3. Task3运行过程中,Task3阻塞了(系统延时或等待信号量等),此时就绪态中,优先级最高的任务Task2执行
  4. Task3阻塞解除了(延时到了或者接收到信号量),此时Task3恢复到就绪态中,抢占TasK2的运行

总结

  • 高优先级任务,优先执行
  • 高优先级任务不停止,低优先级任务无法执行
  • 被抢占的任务将会进入就绪态

3.3 时间片调度

同等优先级任务轮流地享有相同的 CPU 时间(可设置), 叫时间片,在FreeRTOS中,一个时间片就等于SysTick 中断周期

freertos学习之路3-freertos的任务调度_第9张图片

运行前提:

  1. 创建三个任务:Task1Task2Task3
  2. Task1Task2Task3的优先级均为1;即3个任务同等优先级

运行过程

  1. 首先Task1运行完一个时间片后,切换至Task2运行
  2. Task2运行完一个时间片后,切换至Task3运行
  3. Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或等待信号量等),此时直接切换到下一个任务Task1
  4. Task1运行完一个时间片后,切换至Task2运行

总结

  • 同等优先级任务,轮流执行;时间片流转
  • 一个时间片大小,取决为滴答定时器中断周期
  • 注意没有用完的时间片不会再使用,下次任务Task3得到执行,还是按照一个时间片的时钟节拍运行

你可能感兴趣的:(freertos,学习,单片机)