FreeRTOS信号量和互斥量

news2024/11/23 15:39:40

信息量

简介

信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。 前面介绍的队列(queue)可以用于传输数据:在任务之间、任务和中断之间。
消息队列用于传输多个数据,但是有时候我们只需要传递状态,这个状态值需要用一个数值表示。在这种情况下我们只需要维护一个数值,使用信号量效率更高、更节省内存。

特点

1、当计数值大于0,代表有信号量资源。

2、当释放信号量,信号量计数值(资源数)加一。

3、当获取信号量,信号量计数值(资源数)减一。

4、信号量:用于传递状态。

5、当信号量如果最大值被限定为1,那么它就是二值信号量;如果最大值不是1,它就是计数型信号量。

二进制信号量跟计数型信号量的区别

二进制信号量跟计数型的唯一差别,就是计数值的最大值被限定为1

信号量跟队列的对比

 这里的生产者指的是give信号量的任务,消费者是take信号量的任务。

信号量函数  

创建

        使用信号量之前,要先创建,得到一个句柄;使用信号量时,要使用句柄来表明使用哪个信号量。 对于二进制信号量、计数型信号量,它们的创建函数不一样:

                

 创建二进制信号量的函数原型如下:
/* 创建一个二进制信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinary( void );
/* 创建一个二进制信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的指
针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffe
r );
创建计数型信号量的函数原型如下:
/* 创建一个计数型信号量,返回它的句柄。
* 此函数内部会分配信号量结构体
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t ux
InitialCount);
/* 创建一个计数型信号量,返回它的句柄。
* 此函数无需动态分配内存,所以需要先有一个 StaticSemaphore_t 结构体,并传入它的指
针
* uxMaxCount: 最大计数值
* uxInitialCount: 初始计数值
* pxSemaphoreBuffer: StaticSemaphore_t 结构体指针
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount,
 UBaseType_t uxInitialCount,
 StaticSemaphore_t *pxSemaphoreBuffer );

删除

        对于动态创建的信号量,不再需要它们时,可以删除它们以回收内存。

        vSemaphoreDelete 可以用来删除二进制信号量、计数型信号量,函数原型如下:

/*
* xSemaphore: 信号量句柄,你要删除哪个信号量
*/
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );

获取信号量当前计数值大小 

uxSemaphoreGetCount( xSemaphore);

返回值:计数值。参数:信号量的句柄。 

give/take

        二进制信号量、计数型信号量的 give take 操作函数是一样的。这些函数也分为 2 个版本:给任务使用,给 ISR 使用。列表如下:

 xSemaphoreGive 的函数原型如下:

 BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

xSemaphoreGiveFromISR 函数的参数与返回值列表如下:

BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);        

xSemaphoreTake 函数的参数与返回值列表如下 :

BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);

 

xSemaphoreTakeFromISR 的函数原型如下:

 BaseType_t xSemaphoreTakeFromISR( SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken);

这里有一点需要读者留意,ISR函数里面有一个BaseType_t*pxHigherPriorityTaskWoken ,和相对另一个参数TickType_t xTicksToWait却不一样,这里是因为,在中断里面调用take ,因为中断无法被阻塞,我们不能设置需要等待的tick,我们会设置这个参数,来告诉是否有任务因为中断读取信号量而变成了就绪态,之后根据这个值,决定是否进行任务调度,去切换任务。 

主要作用:优先级翻转

简介:优先级翻转:高优先级的任务反而慢执行,低优先级的任务反而优先执行。
实质:无非就是高优先级的任务take信号量失败,导致自己被阻塞,然后低优先级任务乘虚而入,等到低优先级任务执行完,才释放信号量,高优先级任务才得以take到信号量,回到ready状态。
总结:高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)。

 互斥量 

简介

互斥信号量其实就是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中!

优先级继承

当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。 不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

互斥量的使用场合

        在多任务系统中,任务 A 正在使用某个资源,还没用完的情况下任务 B 也来使用的话,就可能导致问题。
        比如对于串口,任务A 正使用它来打印,在打印过程中任务 B 也来打印,客户看到的结果就是A B 的信息混杂在一起。
        上述问题的解决方法是:任务A 访问这些全局变量、函数代码时,独占它,就是上个锁。这些全局变量、函数代码必须被独占地使用,它们被称为临界资源。
         互斥量也被称为互斥锁,使用过程如下:

 互斥量函数

创建   

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

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

动态分配内存:

/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非 NULL 表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );

 静态分配内存:

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

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

 删除

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

 释放

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

 获得

BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);

 互斥量不能在ISR中使用

原因如下:
(1) 互斥信号量有任务优先级继承的机制, 但是中断不是任务,没有任务优先级, 所以互斥信号量只能用与任务中,不能用于中断服务函数。
(2) 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。
FreeRTOS 提供了专门用于在 ISR 中操作的函数,如 xSemaphoreGiveFromISR 和  xSemaphoreTakeFromISR,这些函数经过设计以确保在 ISR 上下文中操作信号量的安全性和有效性。这些函数在实现上会考虑到互斥量的特殊性和需求。
        

总结

信号量:

信号量就是特殊的队列。

队列里使用环形缓冲区存放数据,

信号量里只记录计数值

互斥量:

互斥量就是特殊的队列。

互斥量更是特殊的信号量,

互斥量实现了优先级继承

至于信号量和互斥量的内部机制,我们可以知道,他们都是特殊的队列,实际上和队列的内部机制几乎一样,如果想要了解,可以去看我FreeRTOS消息队列,里面有队列的内部机制讲解。

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

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

相关文章

关于bim数字孪生threejs中使用glb文件大小优化及加载慢的说明(笔记)

在用three.js开发的时候发现,稍微大一点的glb或者fbx文件加载的时候很慢很卡 一直不理解这个卡和慢取决于哪些条件,下面来详细说一下 1、关于模型 不是越大加载越卡顿,而是却决于三角面数量,当累计三角面数量达到3000万时会出现明…

基于SSM的大学生家教管理系统【附源码+LW】

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本大学生家教平台就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

Linux随记(十)

一、harborv2.6.4 --> harbor-offline-installer-v2.11.0-rc3 --> v2.9.4 – 随记 漏洞信息: CVE-2023-20902timing condition in Harbor 2.6.x and below, Harbor 2.7.2 and below, Harbor 2.8.2 and below, and Harbor 1.10.17 and below allows an atta…

shell编程实战

1.1 shell脚本编程的步骤 需求分析:确定功能 命令测试:确定脚本需要的关键命令 编辑脚本 测试脚本 1.2 操作 1.2.1 实验一 1.需求描述 (1)统计网络中的服务器的mac 注:ARP,地址解析协议 注: (2)检查哪些主机开…

乐队谱在哪里找 乐队功能谱怎么做 Guitar Pro8激活码 吉他谱软件

学习乐队谱对于音乐爱好者来说是一种极具乐趣和挑战的体验。无论是追溯经典曲目还是与其他乐手合作,乐队谱都是实现音乐梦想的必备工具。然而,要找到适合练习的乐队谱并制作出符合乐队演奏需求的功能谱并不容易,需要借助一些方法和工具。下面…

visual studio 2022配置和使用protobuf

上图证明,我真的测了好多遍,测了好多版本的protobuf,花了很多时间。不过好在最后在vs2022上测通了。 下载protobuf 这里是protobuf下载的地址。 Releases protocolbuffers/protobuf GitHub 个人使用的3.21.9这个版本才跑通的。 1、首先…

Linux中部署MySQL环境方法(仓库安装)

1.进入MySQL官网 2.进入MySQL社区版下载 3.使用yum方式下载MySQL 4.使找到对应系统的对应包的链接 复制 5.linux命令行中使用命令通过对应链接下载该软件包 rpm -i https://repo.mysql.com//mysql80-community-release-el9-1.noarch.rpm 警告:/var/tmp/rpm-tmp.so…

MySQL数据库——在Centos7环境安装

MySQL在Centos7环境安装 1.切换root用户 安装与卸载中,用户全部切换成为root,安装好后,普通用户也能使用 2.卸载不要的环境 要将自己环境中有关mysql的全都删除,避免安装过程中被影响 ps axj | grep mariadb 先检查是否有mari…

【Linux进阶】windows和linux文件互传的两种方式

前言 我们在windows电脑上使用ssh工具(比如Xshell)来远程登录并使用linux云服务器的时候,难免要将我们的文件传输到linux服务器上,或者将linux服务器的文件传输到我们的windows电脑里,那么,我们要怎么来实…

解决VSCode无法用ssh连接远程服务器的问题

原因: 因为windows自带的ssh无法连接远程服务器,需要用git底下的ssh.exe。 搜了很久,试过很多方法,包括替换掉环境变量中的ssh,但是都无效,最后发现是要在VSCode中配置需要使用哪个ssh.exe。 步骤&#…

第0章_项目方案介绍

文章目录 第0章 项目方案介绍0.1 功能介绍0.2 硬件方案0.3 软件方案0.3.1 上位机方案0.3.2 **中控方案**0.3.3 **传感器方案**0.3.4 **技术难点** 第0章 项目方案介绍 0.1 功能介绍 本课程来自一个真实项目:多个气体传感器的管理。由于气体传感器比较昂贵&#xf…

vue中如何使用echarts和echarts-gl实现三维折线图

一、vue中使用三维折线图 效果图: 二、使用步骤 1.引入库 安装echarts 在package.json文件中添加 "dependencies": {"echarts": "^5.1.2""echarts-gl": "^1.1.1",// "echarts-gl": "^2.0.8…

axios之CancelToken取消请求

从 v0.22.0 开始,Axios 支持以 fetch API 方式—— AbortController 取消请求 此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用 官网链接 1. 背景 最近项目中遇到一个场景,当连续触发一个请求时,如果是同一个接口&#xf…

通讯录项目的实现(基于顺序表)

前言 建议先看顺序表(上卷)、顺序表(下卷),再来看本篇。 思路 通讯录就是由一条条联系人数据组成的。在一条联系人数据中会有一些相关信息:姓名、性别、年龄、电话、住址等。 在“顺序表(上卷…

Ubuntu安装、更新和删除软件

Ubuntu安装、更新和删除软件 问题命令行直接安装、更新和删除软件命令行直接安装软件命令行直接更新软件命令行直接删除软件 手动下载后命令行安装、更新和删除软件手动下载后命令行安装软件手动下载后命令行更新软件手动下载后命令行删除软件 手动下载后在桌面环境下安装、更新…

RocketMQ快速入门:事务消息原理及实现(十)

目录 0. 引言1. 原理2. 事务消息的实现2.1 java client实现(适用于spring框架)2.2 springboot实现 3. 总结 0. 引言 rocketmq 的一大特性就是支持事务性消息,这在诸多场景中有所应用。在之前的文章中我们已经讲解过事务消息的使用&#xff0…

三星DRAM、NAND,“又双叒叕”带头涨价了

据韩国媒体《每日经济新闻》报道,三星电子计划在第三季度上调服务器DRAM和企业级NAND闪存的价格,涨幅预计在15%-20%,主要受人工智能(AI)需求激增的推动。这一举措有望提振公司下半年业绩。 据《经济日报》报道援引业内消息,由于厂…

Linux libreoffice安装 word转pdf 中文乱码(缺少字体解决)

libreoffice 的安装 yum install -y libreoffice版本验证 libreoffice --version参考文章 word转pdf 命令 转换命令 要将Word文档(.doc或.docx)转换为PDF格式,可以使用以下命令: libreoffice --headless --convert-to pdf your_word_document.docx指…

《GPT模型揭秘:数据驱动AI的核心概念与GPT系列对比分析》

DS:《What Are the Data-Centric AI Concepts behind GPT Models?通过三个数据为中心的人工智能目标(训练数据开发、推理数据开发和数据维护)揭示GPT模型背后的数据为中心的人工智能概念》解读—GPT-1/GPT-2/GPT-3系列对比(语料大小参数量解码层数上下文长度隐藏层…

高性价比蓝牙耳机有哪些?2024超高性价比蓝牙耳机推荐

在2024移动互联网高速发展的时代,蓝牙耳机已成为我们生活中不可或缺的一部分。走在街头,低头看手机,滑动屏幕选歌,耳边传来清晰的旋律,这一幕已经成为现代生活的标配。但面对市场上琳琅满目的蓝牙耳机品牌和型号&#…