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

news/2024/12/23 0:34:55/

写在最前

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

参考:

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

1. 任务调度状态

1.1 四种调度状态

在这里插入图片描述

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

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

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

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

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

    才可以进入就绪态

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

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

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

在这里插入图片描述

1.2 状态转换

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

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

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

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

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

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

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

1.3 任务状态列表

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

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

在这里插入图片描述

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

1.4 任务状态例子

不同优先级

假设我们创建了三个任务分别为task1, task2, task3,优先级分别为1,2,3
在这里插入图片描述

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

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

相同优先级

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

在这里插入图片描述

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

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

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

2.1 调度器

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

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

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

freertos提供三种调度方式:

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

2.2 抢占式调度

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

在这里插入图片描述

运行前提:

  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的运行

总结

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

2.3 时间片调度

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

在这里插入图片描述

运行前提:

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

运行过程

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

总结

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

http://www.ppmy.cn/news/22625.html

相关文章

【JavaScript速成之路】JavaScript数据类型

📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言1,变量的数据类型1.1,强类型语言1.2,弱类…

阿尔茨海默氏症救星!经典+量子混合方法加速药物发现

(图片来源:网络)本月,阿尔茨海默氏症的世界被lecanemab震撼了,lecanemab是由美国生物技术公司Biogen与日本制药公司Eisai合作开发的治疗方法。研究表明,对于那些还在困扰着人类的疾病,量子设备将…

AVL树.

目录 一. 概念 二. 节点的定义 三. 基础框架 四. 插入 1.左旋 2.右旋 3.右左旋 4.左右旋 5.总览 五. 验证 一. 概念 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中…

凡人修C传——专栏从凡人到成仙系列目录

这里先感谢博主THUNDER王给我提出来的一个创作建议,让我有了创作的灵感来创建这一篇博客以及凡人修C传这一个系列的文章。 本文最主要的目的就是给大家一个凡人修C传的一个目录,让大家更加容易学到自己想学的地方。 📝【个人主页】&#xff1…

STM32开发(4)----系统启动流程

系统启动流程前言一、系统启动方式二、启动汇编文件分析1. 初始化堆栈指针2. 初始化中断向量表3. 在Reset_Handler中调用 SystemInit4.进入main函数前,初始化用户堆栈总结前言 本章介绍STM32系统启动流程的相关内容,包括对系统启动方式,启动…

Java基础知识(基础篇 适合小白)

Hello World public 访问修饰符 static 关键字 void 返回类型 String 类 args字符串数组 public class HelloWorld {/* 第一个Java程序* 它将输出字符串 Hello World*/public static void main(String[] args) {System.out.println("Hello World"); // 输出 Hello Wo…

栈与队列 || leetcode 20. 有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有…

测试开发之Django实战示例 第一章 创建博客应用

第一章 创建博客应用欢迎来到Django 2 by example的教程。你看到的是目前全网唯一翻译该书的教程。本书将介绍如何创建可以用于生产环境的完整Django项目。如果你还没有安装Django,本章在第一部分中将介绍如何安装Django,之后的内容还包括创建一个简单的…