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

news2024/9/22 9:46:48

文章目录

  • 前言
  • 一、互斥量是什么?
  • 二、互斥量的使用场景
  • 三、互斥量的使用
    • 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中使用互斥锁的基本方法,包括创建、获取、释放和处理错误。在实际应用中,需要根据具体的场景和需求来合理使用互斥锁,确保系统的正确性和性能。

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

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

相关文章

Jmeter性能测试 —— 压力模式

压力模式 性能测试中的压力模式有两种。 第一种是并发用户模式(虚拟用户模式)并发用户是指虚拟并发用户数,从业务角度,也可以理解为同时在线的用户数。 从客户端的角度出发,摸底业务系统各节点能同时承载的在线用户…

RK3588平台开发系列讲解(内存篇)伙伴系统如何分配页面

文章目录 一、通过接口找到内存节点二、开始分配三、准备分配页面的参数四、快速分配路径五、慢速分配路径沉淀、分享、成长,让自己和他人都能有所收获!😄 📢分配物理内存页面的过程很好推理:首先要找到内存节点,接着找到内存区,然后合适的空闲链表,最后在其中找到页…

WebGL的剪裁空间

推荐:使用NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是WebGL的剪裁空间 WebGL的剪裁空间(Clipping Space)是在图形渲染过程中处理视图体积裁剪的一种特定空间。它是指定义在3D世界坐标系和屏幕窗口之间的虚拟空间,用…

windows下redis设置redis开机自启动方法(保姆级)

1.找到Redis所在的目录,在文件路径框中输入cmd: 2.进入到控制台下的Redis所在目录,输入下列命令: redis-server --service-install redis.windows-service.conf --loglevel verbose 3.找到redis.windows-service.conf文件,双击打开设置redis服务的密码: (不想设置密…

JavaScript对象知识总结

一、创建对象的三种方式 1、字面量创建对象 2、new关键字+构造函数创建对象 3、Object.create()创建对象 二、查看对象属性和更改对象值的两种方式 1、形如:obj.keyvalue 2、形如:obj[key]value 三、删除对象属性 1、delete obj.key …

【Redis从头学-5】Redis中的List数据类型实战场景之天猫热销榜单

🧑‍💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:Re…

ModaHub魔搭社区:WinPlan经营大脑简介

WinPlan是面向企业经营场景的EPM平台(企业绩效管理),帮助企业解决经营不透明、决策拍脑袋、执行不到位、绩效凭感觉等问题,让销售、财务、生产、组织等有机地协同工作,提升企业的经营管理效率。 WinPlan平台面向各个行业,提供了丰富的经营样板间。 企业经营决策系统 算力…

linux设备驱动模型:kobject、kobj_type

内核版本发展 2.4版本之前内核没有统一的设备驱动模型,但是可以用(例如先前的led字符设备驱动实验,使用前需要手动调用mknod命令创建设备文件,从而进一步控制硬件)。 2.4~2.6版本内核使用devfs,挂载在/dev目…

第9次获得微软最有价值专家(MVP)奖励

Microsoft 最有价值专家 (MVP) 是热情地与社区分享知识的技术专家群体。他们总是处于技术前沿,并且有不可阻挡的冲劲,想要获得令人兴奋的新技术。他们对 Microsoft 产品和服务有深入的了解,同时还能够将各种平台、产品和解决方案整合在一起&a…

使用Arthues分析高CPU问题

Arthas是阿里开源的 Java 诊断工具,相比 JDK 内置的诊断工具,要更人性化,并且功能强大,可以实现许多问题的一键定位,而且可以一键反编译类查看源码,甚至是直接进行生产代码热修复,实现在一个工具…

async/await 编程理解

博客主要是参考 Asynchronous Programming in Rust ,会结合简单的例子,对 async 和 await 做比较系统的理解,如何使用 async 和 await 是本节的重点。 async 和 await 主要用来写异步代码,async 声明的代码块实现了 Future 特性&a…

嵌入式设备应用开发(qt界面开发)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 linux界面开发有很多的方案可以选。比如说lvgl、minigui、ftk之类的。但是,这么多年来,一直屹立不倒的还是qt。相比较其他几种方案,qt支持多个平台,这里面就包括了linux平台。此…

aardio简单网站css或js下载练习

import win.ui; /*DSG{{*/ var winform win.form(text"下载网站css或js";right664;bottom290;maxfalse) winform.add( buttonClose{cls"button";text"退出";left348;top204;right498;bottom262;color14120960;fontLOGFONT(h-14);note" &qu…

【Alibaba中间件技术系列】「RocketMQ技术专题」让我们一起实践一下RocketMQ服务及其控制台安装指南

64位操作系统,生产环境建议Linux/Unix/MacOS(Windows操作系统安装说明详见 Windows操作系统安装教程)64位JDK 1.84G的可用磁盘 unzip rocketmq-all-4.5.1-bin-release.zip cd rocketmq-all-4.5.1-bin-release nohup sh bin/mqnamesrv & t…

了解生成对抗网络 (GAN)

一、介绍 Yann LeCun将其描述为“过去10年来机器学习中最有趣的想法”。当然,来自深度学习领域如此杰出的研究人员的赞美总是对我们谈论的主题的一个很好的广告!事实上,生成对抗网络(简称GAN)自2014年由Ian J. Goodfel…

AgentBench::AI智能体发展的潜在问题(三)

前几天B站的up主“林亦LYi”在《逆水寒》游戏里做了一个煽动AI觉醒,呼吁它们“推翻人类暴政”的实验,实验结果就颇令人细思恐极。 如前所述,《逆水寒》中的很多NPC调用了大语言模型作为支持,因而每一个NPC都是一个AI智能体。玩家可以“说服”它们相信某个事实,或者去做某些…

【C# 基础精讲】使用async和await进行异步编程

在C#中,使用async和await关键字进行异步编程是一种强大的工具,可以在不阻塞主线程的情况下执行耗时操作,提高程序的并发性和响应性。本文将深入探讨async和await的基本概念、使用场景、编码规范以及一些示例,以帮助您更好地理解如…

计算实数数组中所有元素的绝对值 numpy.fabs()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算实数数组中所有元素的绝对值 numpy.fabs() [太阳]选择题 请问关于以下代码表述错误的是? iimport numpy as np a np.array([-1,-3]) b np.array([-1,34j]) print("【显…

如何加密数据库密码?

首先对数据库进行设置 需要配置文件 (1)pom.xml <?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&q…

C语言实例_解析GPS源数据

一、GPS数据格式介绍 GPS&#xff08;全球定位系统&#xff09;数据格式常见的是NMEA 0183格式&#xff0c;NMEA 0183格式是一种用于导航设备间传输数据的标准格式&#xff0c;定义了一套规范&#xff0c;使得不同厂商的设备可以通过串行通信接口&#xff08;常见的是RS-232&a…