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

【Freertos基础入门】深入浅出freertos互斥量

文章目录

  • 前言
  • 一、互斥量是什么?
  • 二、互斥量的使用场景
  • 三、互斥量的使用
    • 1.创建
  • 2.删除互斥量
  • 3.give和take
  • 四、示例代码
  • 总结


前言

FreeRTOS是一款开源的实时操作系统,提供了许多基本的内核对象,其中包括互斥锁(Mutex)。互斥锁是一种常用的同步机制,用于确保在同一时间内只有一个任务可以访问共享资源,防止竞态条件等并发问题。本文将介绍FreeRTOS中的互斥锁的使用方法和注意事项。


一、互斥量是什么?

当多个任务同时操作一个共享资源时,就可能出现竞态条件(Race Condition)的问题,导致数据错乱或不一致的情况。为了解决这个问题,FreeRTOS提供了互斥量(Mutex)的概念。

可以将互斥量类比为一把锁,只有拿到这把锁的任务才能操作共享资源,其他任务需要等待。互斥量的作用是保护共享资源,确保在同一时间内只有一个任务可以访问它。

具体来说,当一个任务需要访问共享资源时,它首先要尝试获取互斥量。如果互斥量没有被其他任务占用,那么这个任务就可以获得互斥量,相当于拿到了锁,并且可以继续执行。而如果互斥量已经被其他任务占用,那么这个任务就会被阻塞,等待互斥量可用。

一旦任务完成了对共享资源的操作,它需要释放互斥量,相当于释放了锁,这样其他任务就有机会获取互斥量,继续执行对共享资源的操作。

互斥量还支持嵌套,即一个任务在持有互斥量时,可以再次尝试获取互斥量。这样可以在多个层次上获取和释放互斥量,确保资源的正确使用。但要注意,在释放互斥量之前,必须相同次数地释放它,否则会导致其他任务无法获取到互斥量,可能导致死锁问题。

当谈到互斥量,一个生活化的比喻可以是门锁。

想象一下,你和其他人住在同一栋公寓楼里,每个人都有自己的房间。这些房间是共享资源,大家都会使用公共的厨房。现在,你正在做晚餐,需要使用炉灶和炒锅。由于只有一个炉灶和炒锅可供使用,你就安装了一个门锁来保护炉灶和炒锅,让其他人知道你正在使用它们。

在这个比喻中,互斥量就好像是这个门锁。只有先到达的人可以拥有锁的使用权,其他人需要等待锁被释放才能使用炉灶和炒锅。这样做的好处是,可以确保一次只有一个人使用炉灶和炒锅,避免混乱和争夺,同时保证了大家能有有序地使用共享资源的机会。

类似地,FreeRTOS中的互斥量可用于保护共享资源,只有一个任务可以获取互斥量的使用权,其他任务需要等待互斥量释放才能访问共享资源。这种机制保护了共享资源的完整性,避免了并发访问可能导致的竞态条件和数据不一致性问题。

希望这个比喻能够让互斥量的概念更加具体和易于理解。

总之,互斥量是FreeRTOS提供的一种同步机制,用于确保在同一时间内只有一个任务可以访问共享资源,避免了竞态条件的问题。它就像一把锁,任务需要获取锁才能操作共享资源,其他任务需要等待。通过合理使用互斥量,可以保证系统数据的一致性和正确性。

二、互斥量的使用场景

FreeRTOS的互斥量(Mutex)是一种非常有用的同步机制,用于保护共享资源、避免竞态条件和确保数据的一致性。下面是一些常见的使用场景:

共享资源保护: 当多个任务需要同时访问共享资源(如全局变量、设备IO等)时,互斥量可以用于保护这些资源,以确保在同一时间内只有一个任务可以访问。其他任务必须等待互斥量可用时才能进行访问,从而避免竞态条件和数据不一致性。

任务间通信: 互斥量可以用于任务间的通信和同步。例如,一个任务负责生成数据,另一个任务负责处理数据。生成数据的任务可以在生成后使用互斥量释放锁,通知处理数据的任务可以获取锁,开始处理数据。这种方式可以实现任务间的协作和同步。

资源分配与释放: 当有多个任务需要访问有限的资源时,互斥量可以用于分配和释放资源。例如,一块只能同时由一个任务访问的内存区域,可以使用互斥量来管理访问权限。任务需要访问内存时,首先尝试获取互斥量,成功获取则可以访问内存,否则需要等待。

临界区保护: 互斥量可以用于保护临界区,即一段关键的代码,确保在同一时间内只有一个任务可以执行该代码段。这对于需要保护关键数据或临界资源的操作非常重要,以确保数据的完整性和正确性。

任务优先级反转解决方案: 在任务优先级反转的情况下,互斥量可以用于解决该问题。任务优先级反转是指高优先级任务被低优先级任务所阻塞的情况,可能导致系统性能下降。通过使用互斥量,高优先级任务可以在访问共享资源之前阻塞低优先级任务,从而避免任务优先级反转。

这些是FreeRTOS互斥量的常见使用场景,通过合理地应用互斥量,可以保护共享资源、实现任务间的同步和协作,确保数据的一致性和系统的正确性。

三、互斥量的使用

互斥量其实就是一种特殊的二进制信号量。

1.创建

使用互斥量时,先创建、然后去获得、释放它。使用句柄来表示一个互斥量。
创建互斥量的函数有2种:动态分配内存,静态分配内存,函数原型如下:

/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );
/* 创建一个互斥量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个StaticSemaphore_t结构体,并传入它的指针
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer
);

要想使用互斥量,需要在配置文件FreeRTOSConfig.h中定义:

#define configUSE_MUTEXES 1

比如下图步骤:
1、搜索文件
在这里插入图片描述
2、开启互斥量
在这里插入图片描述

2.删除互斥量

使用vSemaphoreDelete删除互斥量

/*
* xSemaphore: 信号量句柄,你要删除哪个信号量, 互斥量也是一种信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore )

3.give和take

他们的参数和我们的信号量差不多,所以我在这就不写了。
give函数原型如下:

/* 释放 */
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

take函数原型如下:

/* 获得 */
BaseType_t xSemaphoreTake(
SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait
);

要注意的是,互斥量不能在ISR中使用。

四、示例代码

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"// 共享资源
int sharedResource = 0;// 互斥量句柄
SemaphoreHandle_t mutex;// 任务函数1
void Task1(void *pvParameters)
{while (1){// 获取互斥量xSemaphoreTake(mutex, portMAX_DELAY);// 在临界区内对共享资源进行操作sharedResource++;printf("Task1: sharedResource = %d\n", sharedResource);// 释放互斥量xSemaphoreGive(mutex);// 等待一段时间vTaskDelay(pdMS_TO_TICKS(1000));}
}// 任务函数2
void Task2(void *pvParameters)
{while (1){// 获取互斥量xSemaphoreTake(mutex, portMAX_DELAY);// 在临界区内对共享资源进行操作sharedResource--;printf("Task2: sharedResource = %d\n", sharedResource);// 释放互斥量xSemaphoreGive(mutex);// 等待一段时间vTaskDelay(pdMS_TO_TICKS(1000));}
}int main(void)
{// 创建互斥量mutex = xSemaphoreCreateMutex();// 创建任务xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);// 启动调度器vTaskStartScheduler();// 如果启动成功,将不会执行到这里while(1);
}

在串口中我们就可以看到打印出来的东西了。

总结

互斥锁是FreeRTOS提供的一个重要的同步机制,用于控制对共享资源的访问。通过仔细使用互斥锁,可以防止并发问题如竞态条件、死锁等的发生。本文简要介绍了在FreeRTOS中使用互斥锁的基本方法,包括创建、获取、释放和处理错误。在实际应用中,需要根据具体的场景和需求来合理使用互斥锁,确保系统的正确性和性能。

相关文章:

【Freertos基础入门】深入浅出freertos互斥量

文章目录 前言一、互斥量是什么?二、互斥量的使用场景三、互斥量的使用1.创建 2.删除互斥量3.give和take四、示例代码总结 前言 FreeRTOS是一款开源的实时操作系统,提供了许多基本的内核对象,其中包括互斥锁(Mutex)。…...

皮爷咖啡基于亚马逊云科技的数据架构,加速数据治理进程

皮爷咖啡(Peet’s Coffee)是美国精品咖啡品牌,于2017年进入中国,为中国消费者带来传统经典咖啡饮品,并特别呈现更加丰富的品质咖啡饮品体验。通过深入应用亚马逊云科技云原生数据库产品Amazon Redshift以及Amazon DMS等…...

C++ string类详解

⭐️ string string 是表示字符串的字符串类&#xff0c;该类的接口与常规容器的接口基本一致&#xff0c;还有一些额外的操作 string 的常规操作&#xff0c;在使用 string 类时&#xff0c;需要使用 #include <string> 以及 using namespace std;。 ✨ 帮助文档&…...

深入浅出Pytorch函数——torch.nn.init.ones_

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 相关文章&#xff1a; 深入浅出Pytorch函数——torch.nn.init.calculate_gain 深入浅出Pytorch函数——torch.nn.init.uniform_ 深入浅出Pytorch函数——torch.nn.init.normal_ 深入浅出Pytorch函数——torch.nn.init.c…...

一、docker及mysql基本语法

文章目录 一、docker相关命令二、mysql相关命令 一、docker相关命令 &#xff08;1&#xff09;拉取镜像&#xff1a;docker pull <镜像ID/image> &#xff08;2&#xff09;查看当前docker中的镜像&#xff1a;docker images &#xff08;3&#xff09;删除镜像&#x…...

【计算机网络】13、ARP 包:广播自己的 mac 地址和 ip

机器启动时&#xff0c;会向外广播自己的 mac 地址和 ip 地址&#xff0c;这个即称为 arp 协议。范围是未经过路由器的部分&#xff0c;如下图的蓝色部分&#xff0c;范围内的设备都会在本地记录 mac 和 ip 的绑定信息&#xff0c;若有重复则覆盖更新&#xff08;例如先收到 ma…...

通过微软Azure调用GPT的接口API-兼容平替OpenAI官方的注意事项

众所周知&#xff0c;我们是访问不通OpenAI官方服务的&#xff0c;但是我们可以自己通过代理或者使用第三方代理访问接口 现在新出台的规定禁止使用境外的AI大模型接口对境内客户使用&#xff0c;所以我们需要使用国内的大模型接口 国内的效果真的很差&#xff0c;现在如果想使…...

回归预测 | MATLAB实现BO-SVM贝叶斯优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现BO-SVM贝叶斯优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现BO-SVM贝叶斯优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介绍程序设计…...

GAN!生成对抗网络GAN全维度介绍与实战

目录 一、引言1.1 生成对抗网络简介1.2 应用领域概览1.3 GAN的重要性 二、理论基础2.1 生成对抗网络的工作原理2.1.1 生成器生成过程 2.1.2 判别器判别过程 2.1.3 训练过程训练代码示例 2.1.4 平衡与收敛 2.2 数学背景2.2.1 损失函数生成器损失判别器损失 2.2.2 优化方法优化代…...

自动驾驶仿真:基于Carsim开发的加速度请求模型

文章目录 前言一、加速度输出变量问题澄清二、配置Carsim动力学模型三、配置Carsim驾驶员模型四、添加VS Command代码五、Run Control联合仿真六、加速度模型效果验证 前言 1、自动驾驶行业中&#xff0c;算法端对于纵向控制的功能预留接口基本都是加速度&#xff0c;我们需要…...

.netcore grpc客户端工厂及依赖注入使用

一、客户端工厂概述 gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。可以通过依赖包Grpc.Net.ClientFactory中的AddGrpcClient进行gRPC客户端依赖注入AddGrpcClient函数提供了许多配置项用于处理一些其他事项&#xff1b;例如AOP、重试策略等 二、案…...

C语言入门_Day7 逻辑运算

目录&#xff1a; 前言 1.逻辑运算 2.优先级 3.易错点 4.思维导图 前言 算术运算用来进行数据的计算和处理&#xff1b;比较运算是用来比较不同的数据&#xff0c;进而来决定下一步怎么做&#xff1b;除此以外还有一种运算叫做逻辑运算&#xff0c;它的应用场景也是用来影…...

什么是Eureka?以及Eureka注册服务的搭建

导包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 htt…...

Docker安装并配置镜像加速器,镜像、容器的基本操作

目录 1.安装docker服务&#xff0c;配置镜像加速器 &#xff08;1&#xff09;安装依赖的软件包 &#xff08;2&#xff09;设置yum源&#xff0c;我配置的阿里仓库 &#xff08;3&#xff09;选择一个版本安装 &#xff08;4&#xff09;启动docker服务&#xff0c;并设置…...

前端 -- 基础 网页、HTML、 WEB标准 扫盲详解

什么是网页 : 网页是构成网站的基本元素&#xff0c;它通常由 图片、链接、文字、声音、视频等元素组成。 通常我们看到的网页 &#xff0c;常见以 .html 或 .htm 后缀结尾的文件&#xff0c; 因此俗称 HTML 文件 什么是 HTML : HTML 指的是 超文本标记语言&#xff0c…...

分布式锁实现方式

分布式锁 1 分布式锁介绍 1.1 什么是分布式 一个大型的系统往往被分为几个子系统来做&#xff0c;一个子系统可以部署在一台机器的多个 JVM(java虚拟机) 上&#xff0c;也可以部署在多台机器上。但是每一个系统不是独立的&#xff0c;不是完全独立的。需要相互通信&#xff…...

C语言小练习(一)

&#x1f31e; “人生是用来体验的&#xff0c;不是用来绎示完美的&#xff0c;接受迟钝和平庸&#xff0c;允许出错&#xff0c;允许自己偶尔断电&#xff0c;带着遗憾&#xff0c;拼命绽放&#xff0c;这是与自己达成和解的唯一办法。放下焦虑&#xff0c;和不完美的自己和解…...

Flask-flask系统运行后台轮询线程

对于有些flask系统&#xff0c;后台需要启动轮询线程&#xff0c;执行特定的任务&#xff0c;以下是一个简单的例子。 globals/daemon.py import threading from app.executor.ops_service import find_and_run_ops_task_todo_in_redisdef context_run_func(app, func):with …...

jsp本质-servlet

jsp本质-servlet 一、jsp文件 <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8"%> <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>JSP Example…...

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...