[FreeRTOS 基础知识] 互斥访问与回环队列 概念

文章目录

    • 为什么需要互斥访问?
    • 使用队列实现互斥访问
      • 休眠和唤醒机制
      • 环形缓冲区


为什么需要互斥访问?

在裸机中,假设有两个函数(func_A, func_B)都要修改a的值(a++),那么将a定义为全局变量a=0,main函数调用func_A();func_B(); 此时a的值为2。因为不存在多任务执行,代码是按照顺序执行的。

在多任务系统中,多个任务在微观上是串行执行,宏观上是并行执行的。 假设两个任务(func_A, func_B)也都要修改a的值(a++),会有什么情况呢?
首先,将修改a的值的代码a++做个拆分:
1、从内存中将a的值读到寄存器R0中;
2、修改寄存器R0的值;
3、将寄存器R0的值写回内存a中。

第一个时间片段执行 func_A,执行完第一步(从内存中将a的值读到寄存器R0中,a=R0=0),任务切换要释放CPU使用权。(任务切换之前会将现场保存下来 R0=0)
第二个时间片段执行 func_B,期间将3个步骤都执行完(a=R0=0;R0=R0+1=0+1=1; R0=a=1)后,任务切换要释放CPU使用权。
第三个时间片段,func_A接着执行,之前先将现场恢复(R0=0),执行后面两个步骤(R0=R0+1=0+1=1; R0=a=1)

在这里插入图片描述
通过上面的两个任务细分执行的过程,会发现当多个任务共用操作一个变量时,会发生异常。为了避免这种异常,引入互斥访问变量的方式。

使用队列实现互斥访问

在这里插入图片描述
当有多个任务操作变a时,为了确保每个任务操作a期间不被其他任务所影响,就调用队列来做隔离,任务B要去读a的值时直接调用队列处理好的数据即可。
队列的任务:1、关闭中断;2、环形缓冲区(操作a的值);3、链表操作;4、打开中断

当任务A调用队列关闭中断后,其他任务不会再被调度执行(相当于逻辑程序),操作完变量a之后,打开中断,此时恢复CPU调度机制。使用队列可以实现互斥访问,避免多个任务同时操作一个变量时造成的异常现象。

RTOS中 调度队列函数接口 :写队列xQueueSend,读队列xQueueReceive

休眠和唤醒机制

任务在读队列的时候会出现两种情况:
第一种情况、读到队列中的值返回;
第二种情况、队列读不到值,将任务休眠

场景:只有两个任务A和任务B,读写a的值
第一个时间片段:任务A 运行,在这个时间段中还没有调用队列修改a的值;
第二个时间片段:任务B运行,读队列,没有得到a的值,将任务B休眠;
第三个时间片段 —— 第五个时间片段:由于任务B处于休眠状态,因此任务A全速运行
第六个时间片段:任务A 写队列修改a的 值,并唤醒任务B
第七个时间片段:任务B 继续执行。
在这里插入图片描述
因此使用队列的方式,不仅能实现互斥访问,还能使用休眠和唤醒机制让CPU更高效的运行。
(注:唤醒任务B,任务B是不会马上执行,要等到下一个tick中断)

写队列的动作:1、修改 Data值;2、唤醒任务wake up
怎么知道唤醒哪个任务呢?队列链表Queue.list,将需要唤醒的任务放在链表里。

读队列的动作:1、有Data值,返回;2、无Data,休眠;
休眠:1、将任务从ReadyList移动到DelayList;2、将任务记录到Queue.list队列链表。

环形缓冲区

在这里插入图片描述
缓冲区本质上就是数组,假设这个缓冲区的长度为8,写缓冲区指针w刚开始在0的位置,每写一个val,指针w位置+(1%8),以此类推,最后的w+(8%8)。这样就形成闭环,也就是环形缓冲区。(读操作也是一样的)

由于链表的大小是有限的,所以当任务写缓冲区的时候发现已经写满了,就会将任务放到Queue.list队列链表中的list for send 链表中
在任务在读缓冲区的值时没有读出来,会将任务放到Queue.list队列链表中的list for receive 链表中

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

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

相关文章

css-vxe列表中ant进度条与百分比

1.vxe列表 ant进度条 <vxe-column field"actualProgress" title"进度" align"center" width"200"><template #default"{ row }"><a-progress:percent"Math.floor(row.actualProgress)"size"s…

Java程序之可爱的小兔兔

题目&#xff1a; 古典问题&#xff0c;有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少? 程序分析&#xff1a; 兔子的规律为数列1,1,2,3,…

C++基础知识——《缺省参数》和《函数重载》

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …

jQuery Mobile 按钮图标

jQuery Mobile 按钮图标 引言 在移动应用和网站设计中,按钮图标是用户界面设计的重要组成部分。它们不仅增加了视觉吸引力,而且有助于提高用户体验。jQuery Mobile 是一个流行的前端框架,用于创建响应式的移动界面。它提供了一系列内置的按钮图标,这些图标可以轻松地应用…

kafka 集群原理设计(三)之启动原理介绍

kafka 集群原理设计(三)之启动原理介绍 业务背景问题描述 现在有三个机器节点192.168.0.200、192.168.0.201、192.168.0.202,分别安装部署zookeeper、 kafka集群,每个topic有3个分区,3个副本,则kafka各个节点在刚启动时,是如何选择哪个Kafka节 点为管理节点,哪个副本为…

【Android进阶学习】Android-广播接收器(Broadcast-Receivers)

android:theme“style/AppTheme” > 现在&#xff0c;无论什么时候Android设备被启动&#xff0c;都将被广播接收器MyReceiver所拦截&#xff0c;并且在onReceive()中实现的逻辑将被执行。 有许多系统产生的事件被定义为类Intent中的静态常量值。下面的表格列举了重要的系…

微积分-导数1(导数与变化率)

切线 要求与曲线 C C C相切于 P ( a , f ( a ) ) P(a, f(a)) P(a,f(a))点的切线&#xff0c;我们可以在曲线上找到与之相近的一点 Q ( x , f ( x ) ) Q(x, f(x)) Q(x,f(x))&#xff0c;然后求出割线 P Q PQ PQ的斜率&#xff1a; m P Q f ( x ) − f ( a ) x − a m_{PQ} \…

前端面试题(基础篇七)

一、谈谈你对webpack的看法 webpack是一个模块打包工具&#xff0c;我们可以使用webpack管理我们的模块依赖&#xff0c;编译输出模块所需的静态文件。它可以很好的管理、打包web开发中所需的html、css、JavaScript以及其他各种静态文件&#xff08;使用的图片、字体图标等&am…

给数据库的表添加字段

周五有一个需求是这样的&#xff1a; 原来数据库有一个表B&#xff0c;现在需要添加一个字段C&#xff0c;我把代码中增删改查部分进行了修改&#xff0c; 比如insert中也添入了字段C。 但没有考虑到一个问题&#xff0c;数据库的兼容性。因为之前的版本已经投入使用了&…

AES 高级加密加速器实验

1、AES介绍 Kendryte K210 内置 AES&#xff08;高级加密加速器&#xff09;&#xff0c;相对于软件可以极⼤的提高 AES 运算速度。 AES 加速器支持多种加密/解密模式&#xff08;ECB,CBC,GCM&#xff09;,多种⻓度的 KEY&#xff08;ECB,CBC,GCM&#xff09;的运算。 AES 加…

Linux常用环境变量

Linux常用环境变量 一、常用的默认的shell环境变量二、环境变量 PATH三、持久化修改环境变量四、常用的环境变量 一、常用的默认的shell环境变量 1、当我们在shell命令行属于一个命令&#xff0c;shell解释器去解释这个命令的时候&#xff0c;需要先找到这个命令. 找到命令有两…

C++模板类原理讲解

C模板类原理讲解 C模板是一种强大的编译期工具&#xff0c;它允许我们创建通用的、类型无关的类和函数。模板的主要目的是实现代码的重用和泛型编程。模板类的原理涉及以下几个方面&#xff1a; 模板的定义和实例化模板的类型参数模板特化模板的编译过程模板的优点和缺点 1.…

【人机交互 复习】第2章 Hadoop

一、概念 1.Hadoop 是一个能够对大量数据进行分布式处理的软件框架&#xff0c;并 且是以一种可靠、高效、可伸缩的方式进行处理的&#xff0c; 2.特点&#xff1a; 高可靠性&#xff0c;高效性&#xff0c;高可扩展性&#xff0c;高容错性 运行在Linux平台上&#xff0c;支持…

鸿蒙 HarmonyOS NEXT星河版APP应用开发—上篇

一、鸿蒙开发环境搭建 DevEco Studio安装 下载 访问官网&#xff1a;https://developer.huawei.com/consumer/cn/deveco-studio/选择操作系统版本后并注册登录华为账号既可下载安装包 安装 建议&#xff1a;软件和依赖安装目录不要使用中文字符软件安装包下载完成后&#xff0…

【Linux 基础】文件与目录管理

1. 文件和目录的基本概念 文件&#xff1a;是数据的集合&#xff0c;可以是文本、图像、视频等。 目录&#xff08;也称为文件夹&#xff09;&#xff1a;是文件和子目录的集合&#xff0c;用于组织文件。 2. 目录和路径 绝对路径&#xff1a;从根目录&#xff08;/&#x…

2021-03-29:加密与解密

前段时间导师分配的任务主要是看《加密与解密》这本书&#xff0c;“书本写的很详细&#xff0c;认真看会看懂的&#xff01;” 是的啊&#xff0c;书本写的很详细&#xff0c;可是作为一个没基础的小白看起来还是挺吃力的&#xff0c;概念一个接一个的出现&#xff0c;虽然看…

【C/C++】常量定义

常量定义 在C中&#xff0c;#define和constexpr都用于定义常量&#xff0c;但它们之间存在显著的差异。以下是它们之间的主要区别&#xff1a; 类型安全&#xff1a; #define&#xff1a;#define是预处理器指令&#xff0c;它在编译之前对源代码进行文本替换。这意味着#define…

LTE和5G基站规划原则

LTE和5G基站规划原则 以下是一些常见的规划原则&#xff1a; 基站覆盖与容量规划 1. **覆盖需求评估**&#xff1a;确定目标区域需要的覆盖范围&#xff0c;包括地理特性和用户分布情况。 2. **容量需求评估**&#xff1a;估算区域内的用户数量及其数据传输需求&#xff0c…

Android应用--简、美音乐播放器添加电话监听

3. 控制音量 4. 获取专辑图片 5. 在线下载歌词 6. 在线搜索音乐 7. 在线下载音乐 8. 实现有趣功能–甩歌 9. 界面美化–实现专辑倒影 10.实现左右界面切换 11.实现在通知栏显示播放状态 12.实现音乐播放的桌面小控件 暂时想到这些功能&#xff0c;如果朋友们有什么建…

Day7 —— 大数据技术之Hive

Hive快速入门系列 Hive的概述什么是Hive&#xff1f;使用Hive的原因 Hive架构Hive安装Hive配置文件修改启动Hive以命令行方式启动&#xff08;在$HIVE_HOME/bin目录下&#xff09;以JDBC连接启动&#xff08;beeline方式连接&#xff09; Hive基本操作Hive数据库操作Hive表操作…