当前位置: 首页 > news >正文

【FreeRTOS】同步与互斥通信-有缺陷的互斥案例

目录

  • 同步与互斥通信
    • 同步与互斥的概念
    • 同步与互斥并不简单
    • 缺陷
    • 分析汇编指令
    • 优化过程 - 关闭中断
    • 时间轴分析
  • 思考时刻


参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》


同步与互斥通信

同步与互斥的概念

一句话理解同步与互斥:我等你用完厕所,我再用厕所。

什么叫同步?就是:哎哎哎,我正在用厕所,你等会。 什么叫互斥?就是:哎哎哎,我正在用厕所,你不能进来。

同步与互斥经常放在一起讲,是因为它们之的关系很大,“互斥”操作可以使用“同步”来实现。我“等”你用完厕所,我再用厕所。这不就是用“同步”来实现“互斥”吗?

再举一个例子。在团队活动里,同事A先写完报表,经理B才能拿去向领导汇报。经理B必须等同事A完成报表,AB之间有依赖,B必须放慢脚步,被称为同步。在团队活动中,同事A已经使用会议室了,经理B也想使用,即使经理B是领导,他也得等着,这就叫互斥。经理B跟同事A说:你用完会议室就提醒我。这就是使用"同步"来实现"互斥"。

有时候看代码更容易理解,伪代码如下:

void  抢厕所(void){if (有人在用) 我眯一会;用厕所;喂,醒醒,有人要用厕所吗;}

假设有A、B两人早起抢厕所,A先行一步占用了;B慢了一步,于是就眯一会;当A用完后叫醒B,B也就愉快地上厕所了。

在这个过程中,A、B是互斥地访问“厕所”,“厕所”被称之为临界资源。我们使用了“休眠-唤醒”的同步机制实现了“临界资源”的“互斥访问”。

同一时间只能有一个人使用的资源,被称为临界资源。比如任务A、B都要使用串口来打印,串口就是临界资源。如果A、B同时使用串口,那么打印出来的信息就是A、B混杂,无法分辨。所以使用串口时,应该是这样:A用完,B再用;B用完,A再用。

同步与互斥并不简单

假设两个任务都是OLED显示的操作,底层都是IIC代码

假设任务A发送了起始信号,此时发生一次调度,任务B也发送了起始信号

在这里插入图片描述

这样IIC时序就被打乱了,IIC时序烂七八糟的

  • 所以使用红框的代码,必须互斥的访问

假设A运行到108行,被切换出去了(全局变量还没有清零),运行任务B,任务B能正常运行,假设任务B运行到一半被切换到任务A,任务A才开始清零,A也可以使用LCD

在这里插入图片描述

如果切换任务发生在108行这一点上,那么A和B都可以同时使用LCD,但是这个概率非常非常低,基本不会在这里产生Tick中断

  • 大部分时间,我们使用全局变量保护这个LCD是没有问题的,但是也有缺陷!~
  • 程序运行很长时间,就有可能发送这样的缺陷!

缺陷

这个缺陷问题在于判断这个变量和设置这个变量被打断了!

在裸机程序里,可以使用一个全局变量或静态变量实现互斥操作,比如要互斥地使用LCD,可以使用如下代码:

 int LCD_PrintString(int x, int y, char *str) {static int bCanUse = 1;if (bCanUse){ bCanUse = 0;/* 使用LCD */bCanUse = 1;return 0;}return -1;}

但是在RTOS里,使用上述代码实现互斥操作时,大概率是没问题的,但是无法确保万无一失。

假设如下场景:有两个任务A、B都想调用LCD_PrintString,任务A执行到第4行代码时发现bCanUse为1,可以进入if语句块,它还没执行第6句指令就被切换出去了;然后任务B也调用LCD_PrintString,任务B执行到第4行代码时也发现bCanUse为1,也可以进入if语句块使用LCD。在这种情况下,使用静态变量并不能实现互斥操作。

上述例子中,是因为第4、第6两条指令被打断了,那么如下改进:在函数入口处先然让bCanUse减一。这能否实现万无一失的互斥操作呢?

 int LCD_PrintString(int x, int y, char *str) {static int bCanUse = 1;bCanUse--;if (bCanUse == 0){ /* 使用LCD */bCanUse++;return 0;}else{bCanUse++;return -1;}}

进入这个函数,bCanUse变量就减减,初值=1,减减后等于0
然后判断这个变量是否等于0,然后就执行下面的语句了
如果任务A能够执行完这个自减语句,才发生调度,执行任务B,在任务B里bCanUse先减减,减完就变成-1了,无法使用LCD

分析汇编指令

把bCanuse指令拆分一下,把第4行的代码使用汇编指令表示如下:

04.1 LDR R0, [bCanUse]  	// 读取bCanUse的值,存入寄存器R004.2 DEC R0, #1     	    // 把R0的值减一04.3 STR R0, [bCanUse]      // 把R0写入变量bCanUse 

在这里插入图片描述

假设如下场景:有两个任务A、B都想调用LCD_PrintString,任务A执行到第04.1行代码时读到的bCanUse为1,存入寄存器R0就被切换出去了;然后任务B也调用LCD_PrintString,任务B执行到第4行时发现bCanUse为1并把它减为0,执行到第5行代码时发现条件成立可以进入if语句块使用LCD,然后任务B也被切换出去了;现在任务A继续运行第04.2行代码时R0为1,运行到第04.3行代码时把bCanUse设置为0,后续也能成功进入if的语句块。在这种情况下,任务A、B都能使用LCD

优化过程 - 关闭中断

上述方法不能保证万无一失的原因在于:**在判断过程中,被打断了。**如果能保证这个过程不被打断,就可以了:通过关闭中断来实现

示例1的代码改进如下:在第5~7行前关闭中断。
没有办法产生Tick中断,无法调度,所以就不会冲突了~

 int LCD_PrintString(int x, int y, char *str) {static int bCanUse = 1;disable_irq();if (bCanUse){ bCanUse = 0;enable_irq();/* 使用LCD */bCanUse = 1;return 0;}enable_irq();return -1;}

示例2的代码改进如下:在第5行前关闭中断。

 int LCD_PrintString(int x, int y, char *str) {static int bCanUse = 1;disable_irq();bCanUse--;enable_irq();if (bCanUse == 0){ /* 使用LCD */bCanUse++;return 0;}else{disable_irq();bCanUse++;enable_irq();return -1;}}

时间轴分析

现在任务A和任务B都使用同一个函数,都想打印自己的信息

在这里插入图片描述

看时间轴,B在不断地判断,不断地失败,耗费了CPU资源
在这里插入图片描述
这种使用全局变量和关闭中断的方法,可以实现打印,但是太消耗CPU资源

那我们能不能实现A打印的过程中,B再来访问,B就阻塞,等待A执行完,用A唤醒B? 如下图所示:

在这里插入图片描述

思考时刻

  • 后面用信号量互斥量完成这些目标

相关文章:

【FreeRTOS】同步与互斥通信-有缺陷的互斥案例

目录 同步与互斥通信同步与互斥的概念同步与互斥并不简单缺陷分析汇编指令优化过程 - 关闭中断时间轴分析 思考时刻 参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》 同步与互斥通信 同步与互斥的概念 一句话理解同步与互斥:我等你用完厕所,我再…...

Docker 安装 Python

Docker 安装 Python 在当今的软件开发领域,Docker 已成为一项关键技术,它允许开发人员将应用程序及其依赖环境打包到一个可移植的容器中。Python,作为一种广泛使用的高级编程语言,经常被部署在 Docker 容器中。本文将详细介绍如何在 Docker 中安装 Python,以及如何配置环…...

外泌体相关基因肝癌临床模型预测——2-3分纯生信文章复现——4.预后相关外泌体基因确定单因素cox回归(2)

内容如下: 1.外泌体和肝癌TCGA数据下载 2.数据格式整理 3.差异表达基因筛选 4.预后相关外泌体基因确定 5.拷贝数变异及突变图谱 6.外泌体基因功能注释 7.LASSO回归筛选外泌体预后模型 8.预后模型验证 9.预后模型鲁棒性分析 10.独立预后因素分析及与临床的…...

C++: Map数组的遍历

在C中,map是一个关联容器,它存储的元素是键值对(key-value pairs),其中每个键都是唯一的,并且自动根据键来排序。遍历map的方式有几种,但最常用的两种是使用迭代器(iterator&#xf…...

【Windows】Bootstrap Studio(网页设计)软件介绍及安装步骤

软件介绍 Bootstrap Studio 是一款专为前端开发者设计的强大工具,主要用于快速创建现代化的响应式网页和网站。以下是它的主要特点和功能: 直观的界面设计 Bootstrap Studio 提供了直观的用户界面,使用户能够轻松拖放元素来构建网页。界面…...

二维舵机颜色追踪,使用树莓派+opencv+usb摄像头+两个舵机实现颜色追踪,采用pid调控

效果演示 二维云台颜色追踪 使用树莓派opencvusb摄像头两个舵机实现颜色追踪,采用pid调控 import cv2 import time import numpy as np from threading import Thread from servo import Servo from pid import PID# 初始化伺服电机 pan Servo(pin19) tilt Serv…...

c进阶篇(四):内存函数

内存函数以字节为单位更改 1.memcpy memcpy 是 C/C 中的一个标准库函数&#xff0c;用于内存拷贝操作。它的原型通常定义在 <cstring> 头文件中&#xff0c;其作用是将一块内存中的数据复制到另一块内存中。 函数原型&#xff1a;void *memcpy(void *dest, const void…...

新手入门:无服务器函数和FaaS简介

无服务器&#xff08;Serverless&#xff09;架构的价值在于其成本效益、弹性和扩展性、简化的开发和部署流程、高可用性和可靠性以及使开发者能够专注于业务逻辑。通过自动化资源调配和按需计费&#xff0c;无服务器架构能够降低成本并适应流量变化&#xff0c;同时简化开发流…...

基于Transformer的端到端的目标检测 | 读论文

本文正在参加 人工智能创作者扶持计划 提及到计算机视觉的目标检测&#xff0c;我们一般会最先想到卷积神经网络&#xff08;CNN&#xff09;&#xff0c;因为这算是目标检测领域的开山之作了&#xff0c;在很长的一段时间里人们都折服于卷积神经网络在图像处理领域的优势&…...

6.8应用进程跨网络通信

《计算机网络》第7版&#xff0c;谢希仁 理解socket通信...

redis布隆过滤器原理及应用场景

目录 原理 应用场景 优点 缺点 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种空间效率很高的随机数据结构&#xff0c;它利用位数组和哈希函数来判断一个元素是否存在于集合中。 原理 数据结构&#xff1a; 位数组&#xff1a;一个由0和1组成的数组&#xff0c;初始…...

vue+openlayers之几何图形交互绘制基础与实践

文章目录 1.实现效果2.实现步骤3.示例页面代码3.基本几何图形绘制的关键代码 1.实现效果 绘制点、线、多边形、圆、正方形、长方形 2.实现步骤 引用openlayers开发库。加载天地图wmts瓦片地图。在页面上添加几何图形绘制的功能按钮&#xff0c;使用下拉列表&#xff08;sel…...

「多模态大模型」解读 | 突破单一文本模态局限

编者按&#xff1a;理想状况下&#xff0c;世界上的万事万物都能以文字的形式呈现&#xff0c;如此一来&#xff0c;我们似乎仅凭大语言模型&#xff08;LLMs&#xff09;就能完成所有任务。然而&#xff0c;理想很丰满&#xff0c;现实很骨感——数据形态远不止文字一种&#…...

Redis深度解析:核心数据类型与键操作全攻略

文章目录 前言redis数据类型string1. 设置单个字符串数据2.设置多个字符串类型的数据3.字符串拼接值4.根据键获取字符串的值5.根据多个键获取多个值6.自增自减7.获取字符串的长度8.比特流操作key操作a.查找键b.设置键值的过期时间c.查看键的有效期d.设置key的有效期e.判断键是否…...

C语言 指针和数组——指针的算术运算

目录 指针的算术运算 指针加上一个整数 指针减去一个整数 指针相减 指针的关系比较运算 小结 指针的算术运算 指针加上一个整数 指针减去一个整数 指针相减 指针的关系比较运算 小结  指针变量 – 指针类型的变量&#xff0c;保存地址型数据  指针变量与其他类型…...

[C++][CMake][CMake基础]详细讲解

目录 1.CMake简介2.大小写&#xff1f;3.注释1.注释行2.注释块 4.日志 1.CMake简介 CMake是一个项目构建工具&#xff0c;并且是跨平台的 问题 – 解决 如果自己动手写Makefile&#xff0c;会发现&#xff0c;Makefile通常依赖于当前的编译平台&#xff0c;而且编写Makefile的…...

CCD技术指标

CCD尺寸&#xff0c;即摄象机靶面。原多为1/2英寸&#xff0c;现在1/3英寸的已普及化&#xff0c;1/4英寸和1/5英寸也已商品化。CCD像素&#xff0c;是决定了显示图像的清晰程度&#xff0c;。CCD是由面阵感光元素组成&#xff0c;每一个元素称为像素&#xff0c;像素越多&…...

SpringBoot系列——使用Spring Cache和Redis实现查询数据缓存

文章目录 1. 前言2. 缓存2.1 什么是缓存2.2 使用缓存的好处2.3 缓存的成本2.4 Spring Cache和Redis的优点 3. Spring Cache基础知识3.1 Spring Cache的核心概念3.2 Spring Cache的注解3.2.1 SpEL表达式3.2.2 Cacheable3.2.3 CachePut3.2.4 CacheEvict 4. 实现查询数据缓存4.1 准…...

【算法】(C语言):冒泡排序、选择排序、插入排序

冒泡排序 从第一个数据开始到第n-1个数据&#xff0c;依次和后面一个数据两两比较&#xff0c;数值小的在前。最终&#xff0c;最后一个数据&#xff08;第n个数据&#xff09;为最大值。从第一个数据开始到第n-2个数据&#xff0c;依次和后面一个数据两两比较&#xff0c;数值…...

iOS项目怎样进行二进制重排

什么是二进制重排 &#xff1f; 在iOS项目中&#xff0c;二进制重排&#xff08;Binary Reordering 或者 Binary Rearrangement&#xff09;是一种优化技术&#xff0c;主要目的是通过重新组织应用程序的二进制文件中的代码和数据段&#xff0c;来提高应用程序的性能&#xff…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...