关于µC/OS-III 多任务的基本理解

news2025/1/24 22:47:33

关于µC/OS-III 多任务的基本理解

任务和任务管理是 RTOS 的核心,且大多数项目使用 RTOS 的目的就是为了使用 RTOS 的多任务管理能力。 µC/OS-III作为经典的RTOS,了解并学习其任务管理机制,是非常有必要的。


文章目录

  • 关于µC/OS-III 多任务的基本理解
  • 一、单任务系统和多任务系统
    • 1.单任务系统
    • 2.多任务系统
  • 二、 µC/OS-III 的任务状态
  • 三、 µC/OS-III 的任务优先级
  • 四、 µC/OS-III 的任务调度方式
    • 1.抢占式调度
    • 2.时间片调度
  • 五、 任务操作函数
    • 1.任务堆栈
    • 2.任务创建
    • 3.任务删除
    • 4.任务挂起
    • 5.任务恢复


一、单任务系统和多任务系统

1.单任务系统

单任务系统就是在裸机上编程,一般都是在 main()函数初始化完成后使用一个while大循环,在循环中顺序地调用相应地函数以处理相应的事务,在while(1)循环中插入各种中断服务函数,整个逻辑顺序依次而行,所以我们也一般称为“流水账”编程方式。如下图所示:
在这里插入图片描述

可以看出,整个代码在while大循环中依次执行,其中部分地方插入点中断,这种框架的优势就是代码较易读,基本上函数调用的顺序就是整个软件各个模块的执行顺序;但是这种框架短板也非常明显,那就是对整个软件各个模块时效控制是很低的,没有轻重缓急之分,比如函数1是控制灯闪烁的函数,需要循环一圈才会调用一次,而且因为不知道函数2和函数2以及中断的执行时间,所以你也没法确定你的闪烁周期,如果删除或增加一个函数模块,你这个周期还会变。

2.多任务系统

多任务系统在处理事务的实时性上比单任务系统要好得多,从宏观上来看,多任务系统的多个任务是可以“并行”的,紧急的事务就可以提高优先级被CPU 优先处理。要注意的是,µC/OS-III 作为单核CPU上的操作系统,其实同一时刻CPU只能处理一个任务,所说的多任务并行其实是通过高效的任务调度算法合理分配各个任务占用CPU的时间,使得各个任务都会根据配置高效运行,所以看起来各个任务像是“并行”一样。如下图所示:
在这里插入图片描述
从上图可以看出,相较于单任务系统而言,多任务系统的任务是具有优先级的,高优先级的任务可以像中断的抢占机制一样,抢占低优先级任务的运行,从而获得 CPU 的使用权;各个任务时效也是可以根据配置参数进行配置的,整个系统的实时性和可控性大大提高。

二、 µC/OS-III 的任务状态

µC/OS-III 中任务存在五种状态,分别为休眠态、就绪态、运行态、挂起态和中断态,某一时刻一个任务一定是处于这五种状态中的一种, 整个µC/OS-III 中的五种任务状态之间的转换图如:
在这里插入图片描述
这是经典的µC/OS-III任务状态转换图,标准了五种不同任务状态的转化方式
■. 休眠态:通过函数 OSTaskDel()删除的任务就会回到休眠态,这里所说的删除,并非将任务从代码空间中删除,而仅仅是将任务切换到休眠态,让 µC/OS-III 内核不再管理这个任务,需要通过调用函数 OSTaskCreate()对一个处于休眠态的任务进行重新创建。
■. 就绪态:准备好运行但还未运行时的任务就处于就绪态。此时任务处于µC/OS-III 就绪列表OSRdylist[X] ,X表示任务优先级数值0-31(32位变量,由高位到低位依次排列)。
■. 运行态:对于单核 CPU 的 MCU 而言,就是是当前正在运行的且唯一的任务所处状态,称为运行态。
■. 挂起态:运行态任务因延时或等待某事件被挂起,例如等待信号量、消息队列或事件标志等,这时运行态任务就会让出 CPU 的使用权,切换到挂起态等待事件发生。 当等待的事件发生后,处于挂起态的任务就会切换到就绪态,等待任务调度器调度运行。
■. 中断态:处于运行态任务被打断,CPU跳转去执行中断服务函数,原本属于运行态的任务会切换到中断态,直到中断结束,再切换回来继续运行

总结:
A. 创建的任务默认是就绪态
B. 被删除的任务,转为休眠态
C. 仅就绪态和中断态可转变成运行态
D. 其他状态的任务要运行,必须转成就绪态

三、 µC/OS-III 的任务优先级

在µC/OS-III中,优先级是决定任务调度器如何分配 CPU 使用权的因素之一。因此µC/OS-III中每一个任务都被分配一个0~(OS_CFG_PRIO_MAX-1)的任务优先级,宏 OS_CFG_PRIO_MAX 表示最大优先级数, 并且 µC/OS-III 中一个任务只能有一个优先级,一个优先级下可以有多个任务。

在 cpu_cfg.h文件中有宏CPU_CFG_LEAD_ZEROS_ASM_PRESENT,该宏用于配置 µC/OSIII 使用硬件指令的方法或是软件算法的方法计算前导零数量, µC/OS-III 使用位图的方式记录当前系统中存在的所有任务优先级, 在 µC/OS-III 系统中存在的最高任务优先级时,就会使用到前导零计数。前导置零指指令CPU_CntLeadZeros():简单理解就是计算一个32位数头部有多少个0,OS_PrioGetHighest()函数通过前导置0指令获得最高优先级。

µC/OS-III 的任务优先级高低与其对应的任务优先级数值是成反比的,也就是说,任务优先级数值为 0 的任务是最高优先级的任务,任务优先级数值为(OS_CFG_PRIO_MAX-1)的任务是优先级最低的任务。

四、 µC/OS-III 的任务调度方式

任务调度:就是任务调度器是使用相关算法来决定当前需要执行的哪个任务,在µC/OS-III 中有两种任务调度规则:

1.抢占式调度

首先已经知道在µC/OS-III 每一个任务都会根据其重要性被分配一个任务优先级,抢占式调度的意思任务优先级高的任务就能够抢占任务优先级低的任务,从而获得 CPU的使用权。抢占式调度特点如下:

A:高优先级优先执行
B:高优先级任务不停止,低优先级任务无法执行
C:被抢占的任务会进入就绪态
D:被挂起的高优先级的任务所等待的事件在中断中发生,中断服务函数退出后不会返回任务优先级低的任务运行,会直接返回任务优先级高的任务去运行

2.时间片调度

µC/OS-III 每一个优先级下可能不止一个任务,那么这些任务的优先级都相同,此时又该怎么调度这些任务呢?

当这些具有相同任务优先级的任务就绪时,任务调度器会根据用户设置的任务时间片轮流地运行这些任务,当然这些任务的运行依然会被任务优先级更高的任务抢占。时间片调度特点如下:

A:同等优先级任务,轮流执行,根据时间片流转依次
B:一个时间片大小取决于滴答定时器中断频率
C:每个任务可以定义自己的时间片长度
D:没有使用的时间片,下次执行不会累加,依旧是初始的时间长度

时间片是依一次系统时钟节拍为单位的,uCOS默认设置的任务时间片为100,则当前任务运行100次时钟节拍之后就切换到相同任务优先级的任务中。

五、 任务操作函数

将任务操作函数之前,先说一个重要概念一一任务堆栈

1.任务堆栈

µC/OS-III 中每个任务都有自己独立的堆栈空间,这个栈空间大小是在创建任务时就确定好的,任务中函数中的局部变量、函数调用时的现场保护和现场恢复等都是要使用到该栈空间的。创建任务函数如下:

void  OSTaskCreate (OS_TCB        *p_tcb,       /*指向任务控制块的指针*/ 
                    CPU_CHAR      *p_name,      /*指向任务名字*/
                    OS_TASK_PTR    p_task,      /*指向任务函数的指针*/
                    void          *p_arg,       /*传递给任务函数的参数*/
                    OS_PRIO        prio,        /*任务优先级,越小优先级越高*/
                    CPU_STK       *p_stk_base,  /*指向任务栈的起始地址指针*/
                    CPU_STK_SIZE   stk_limit,   /*任务使用的警戒线*/
                    CPU_STK_SIZE   stk_size,    /*任务堆栈大小*/
                    OS_MSG_QTY     q_size,      /*任务内嵌消息队列的大小*/
                    OS_TICK        time_quanta, /*任务时间片*/
                    void          *p_ext,       /*指向用户扩展内存的指针*/
                    OS_OPT         opt,         /*任务选项共5个*/
                    OS_ERR        *p_err)       /*指向接收错误代码变量指针*/

其中参数 p_stk_base 就是任务栈空间的首地址,参数 stk_size 就是任务栈空间的大小,对于 STM32 所使用的 ARM Cortex-M 对应的 CPU_STK 定义如下所示:

typedef unsigned int CPU_INT32U;
typedef CPU_INT32U CPU_STK

因此 stk_size 表示的任务栈大小的单位为字,因此实际栈大小为 :stk_size*4(1 字为 4 字节)字节。

2.任务创建

1.创建任务函数OSTaskCreat():任务创建后会进入就绪态,(如果是多个任务会根据创建的先后顺序以此执行,然后才会根据优先级独立运行,所以要根据运行顺序调整创建顺序或优先级,或者创建任务时使用临界区,然后创建完成释放临界区,任务会根据优先级执行。
2.任务创建流程
A. 定义函数入口参数(任务控制块、堆栈大小、优先级、任务名称…….
B. 调用创建任务函数
C. 实现函数功能
D. 创建后任务就立即进入就绪态,

注意事项:
1.在调用任何关于μCOS3函数之前必须先初始化μCOS3,仅需要初始化一次即可OSInit(&err);
2.任务创建后是不会直接运行的,需要开启任务调度器,任务才会运行,仅需要调用一次即可OSStart(&err);

3.任务删除

1.删除任务函数OSTaskDel (OS_TCB *p_tcb,OS_ERR *p_err):不需要该任务时可以删除任务,但是不会释放该任务堆栈和删除码,

注意事项:不能删除空闲任务

注意:中断中不能创建和删除任务,只能在任务中执行,任务可以删除自己

4.任务挂起

挂起任务:OSTaskSuspend (OS_TCB *p_tcb,OS_ERR *p_err):可以无条件(无论该任务处于什么状态(被删除的除外))的挂起任务,被挂起的任务不会参与任务调度,如果被挂起的任务是当前真正执行的,那么会发生任务调度,将CPU使用权交给另一个任务,无论优先级如何,被挂起之后某人任务不再执行直到任务恢复。当出入的任务控制块指针是0,表示挂起任务自身。

注意事项:
挂起任务本质就是将就绪列表的任务移除(不是删除),不参与运行

5.任务恢复

OSTaskResume (OS_TCB *p_tcb,OS_ERR *p_err):用于恢复被OSTaskSuspend()函数挂起的任务,可多次调用OSTaskSuspend挂起同一个任务,解挂需要调用相同次数的OSTaskResume()才能解挂;恢复任务的目的是将任务插回就绪列表。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/995991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

进阶C语言-指针的进阶(中)

指针的进阶 📖5.函数指针📖6.函数指针数组📖7.指向函数指针数组的指针📖8.回调函数 📖5.函数指针 数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。 函数指针 - 指向函数的指针 - 存放的…

【Java】session的工作原理

文章目录 一、session的概念及特点session概念session主要有以下的这些特点 二、为什么要使用session三、session的工作原理四、session的生命周期Session何时生效Session何时失效 五、session的性能瓶颈六、session实现登录状态的控制 一、session的概念及特点 session概念 …

无涯教程-JavaScript - COUPDAYSNC函数

描述 COUPDAYSNC函数返回从结算日期到下一个息票日期的天数。 语法 COUPDAYSNC (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证…

基于第二代 ChatGLM2-6B P-Tuning v2 微调训练医疗问答任务

今天是教师节,恭祝全体老师们节日快乐!😊 一、ChatGLM2-6B 在本专栏前面文章中实验了使用 ChatYuan-large-v2 Freeze 微调训练医疗问答任务,训练后效果整体还可以,这篇文章继续探索使用最近比较火的 ChatGLM 官方推出…

docker镜像详解

目录 什么是docker镜像镜像相关命令docker pulldocker imagesdocker searchdocker rmi导出 / 导入镜像 镜像分层镜像摘要镜像摘要的作用分发散列值 什么是docker镜像 Docker镜像是Docker容器的基础组件,它包含了运行一个应用程序所需的一切,包括代码、运…

Sharding-Jdbc(2):Sharding-Jdbc入门案例

1 前置条件 搭建读写分离的数据库环境,搭建方法如下文,目标数据库test Mysql性能优化(5):主从同步原理与实现_mysql主从配置优化_不死鸟.亚历山大.狼崽子的博客-CSDN博客 2 新建maven项目 3 pom引入依赖 <?xml version="1.0" encoding="UTF-8"…

《protobuf》基础语法2

文章目录 枚举类型ANY 类型oneof 类型map 类型改进通讯录实例 枚举类型 protobuf里有枚举类型&#xff0c;定义如下 enum PhoneType {string home_addr 0;string work_addr 1; }同message一样&#xff0c;可分为 嵌套定义&#xff0c;文件内定义&#xff0c;文件外定义。不…

二维码智慧门牌管理系统:智能化地址管理,提升社会治理效率

文章目录 前言一、地址管理挑战二、二维码智慧门牌管理系统解决方案 前言 随着科技的飞速发展&#xff0c;我们的生活正经历前所未有的变革。尤其是智能化技术&#xff0c;已经深刻影响了我们的日常生活和工作环境。然而&#xff0c;在某些领域&#xff0c;如地址管理和社会治…

十大免费好用的视频软件推荐,新手小白必备

很多人都在使用视频软件进行编辑&#xff0c;那么你们知道哪些视频软件是免费的而且还好用&#xff1f; 现在很多小伙伴比较喜欢用手机编辑视频&#xff0c;而这些剪辑软件具有领先的智能化AI技术&#xff0c;让你不用绿幕就能一键挖出图像&#xff0c;不仅可以一键挖出三维人…

获取板块分类并展示

板块分类也会变动&#xff0c;偶尔看下&#xff0c;利于总体分析大盘 https:dapanyuntu.com/ 该网站含有板块信息 分析接口 搜素关键字 拷贝curl到curl解析工具&#xff0c;去掉无用的参数&#xff0c;生成requests代码 尝试nginx反代接口 server {listen 443;loca…

汇率失守7.3关口

号外&#xff1a;9.8教链内参《被判入狱1万年》。 拉锯多时的离岸人民币汇率USDCNH失守7.3关口&#xff0c;隔夜冲破7.36的高位。 为什么7.3是一个关键关口&#xff1f;因为这里是2022年10月底、11月初时曾经测试过的支撑位&#xff08;从CNH的角度说&#xff09;。 如果支撑位…

微信视频号挂公众号文章链接新方法:不限次数,不限号

当看到自己身边的人&#xff0c;通过我分享的方法绑定成功&#xff0c;那是开心到起飞了。 因为我知道&#xff1a;外面不靠谱的人很多&#xff01;分享不靠谱方法的人&#xff0c;可谓是更多。 为什么我要主动分享视频号评论区挂公众号文章链接&#xff1f;总有人伸张正义&a…

java中log使用总结

目录 一、概述1.1. 核心日志框架1.2 门面日志框架 二、最佳实践2.1 核心日志框架API包2.2 门面日志框架依赖2.3 集成使用2.3.1 集成jcl2.3.2 集成slf4j2.3.2.1 slf4j集成单一框架2.3.2.2 slf4j整合混合框架 三、总结3.1 所有相关包3.1.1 核心日志框架包3.1.2 门面日志框架3.1.3…

Python元类(metaclass)

Python 是一种强大的编程语言&#xff0c;一部分得益于其语言设计中独特的元类&#xff08;Metaclass&#xff09;机制。尽管元类的概念在刚开始接触时可能会让人感到困惑&#xff0c;但一旦理解了它们的工作原理和应用方式&#xff0c;我们就可以用它们做出强大且灵活的抽象。…

无涯教程-JavaScript - COUPDAYS函数

描述 COUPDAYS函数返回包含结算日期的息票期限内的天数。 语法 COUPDAYS (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 RequiredMaturity 证券的到…

Nginx重写功能

Nginx重写功能 一、Nginx常见模块二、访问路由location2.1location常用正则表达式2.2、location的分类2.3、location常用的匹配规则2.4、location优先级排列说明2.5、location示例2.6、location优先级总结2.7、实例2.7.1、location/{}与location/{}2.7.2、location/index.html{…

joplin更新后找不到文章

Joplin的数据默认是存储在C:\Users\Username.config\joplin-desktop下的。我修改为了D:\joplinnotes 这样就导致在升级覆盖安装的时候&#xff0c;笔记丢失路径。如果记不起之前笔记保存在哪里&#xff0c;也可以搜索类似文件来回忆之前自己保存笔记的位置 cache\ plugins\ re…

黑马JVM总结(三)

&#xff08;1&#xff09;栈内存溢出 方法的递归调用&#xff0c;没有设置正确的结束条件&#xff0c;栈会有用完的一天&#xff0c;导致栈内存溢出 可以修改栈的大小&#xff1a; 再次运行&#xff1a;减少了次数 案例二&#xff1a; 两个类的循环应用问题&#xff0c;导致Js…

注解生效激活(idea)

File---------settings-----------Build,Execution,Deployment-----------Compiler------- Annotation Processors

数据分析和可视化平台:Splunk Enterprise for mac v9.1.1激活版 兼容m1

Splunk Enterprise 是一个数据分析和可视化平台&#xff0c;可帮助企业理解其数据。虽然没有适用于 Mac OS 的 Splunk Enterprise 官方版本&#xff0c;但他们确实为 Mac OS 提供了一个名为“Splunk Light”的应用程序&#xff0c;它提供了基本的数据索引、搜索和仪表板。或者&…