FreeRTOS信号量和互斥量

信息量

简介

信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。 前面介绍的队列(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.mzph.cn/web/36103.shtml

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

相关文章

计算机网络:408考研|湖科大教书匠|原理参考模型I|学习笔记

系列目录 计算机网络总纲领 计算机网络特殊考点 计算机网络原理参考模型I 计算机网络原理参考模型II 目录 系列目录更新日志数据链路层(Data Link Layer)一、基本概念二、三个重要问题三、 🌟点对点协议(PPP, Point-to-Point Protocol)四、 以太网五、802.11 无线局…

数据结构-分析期末选择题考点(串、数组)

竹月光中诗世界 松风影里酒生涯 目录 串的常见考法(一)BF算法 串的常见考法(二)KMP求 next数组 串的常见考法(三)串的概念及性质 串的常见考法(四)给出主串求子串数量 数组的常见…

使用 nvm 管理 Node 版本及 pnpm 安装

文章目录 GithubWindows 环境Mac/Linux 使用脚本进行安装或更新Mac/Linux 环境变量nvm 常用命令npm 常用命令npm 安装 pnpmNode 历史版本 Github https://github.com/nvm-sh/nvm Windows 环境 https://nvm.uihtm.com/nvm.html Mac/Linux 使用脚本进行安装或更新 curl -o- …

如何在AWS上使用免费的服务器

要在AWS上免费使用的服务器,你可以按照以下步骤操作: (1)注册AWS账户: 访问AWS官方网站(https://aws.amazon.com/cn/),点击右上角的“完成注册”,按照页面提示填写相关…

华为BGP路由实验基础1------用物理口建立对等体

1.用物理口做BGP建立对等体建立BGP连接 实验拓扑: 实验步骤: 1.完成基本配置 sys [Huawei]sys AR1 [AR1]undo in e [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [AR1-GigabitEthernet0/0/0]q [AR1] sys [Huawei]sys AR2 [AR2]undo i…

【Python】已解决:Python正确安装文字识别库EasyOCR

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决:Python正确安装文字识别库EasyOCR 一、分析问题背景 在使用Python进行图像处理和文字识别时,EasyOCR是一个流行的库,它基于PyTorch&…

【算法刷题 | 动态规划14】6.28(最大子数组和、判断子序列、不同的子序列)

文章目录 35.最大子数组和35.1题目35.2解法:动规35.2.1动规思路35.2.2代码实现 36.判断子序列36.1题目36.2解法:动规36.2.1动规思路36.2.2代码实现 37.不同的子序列37.1题目37.2解法:动规37.2.1动规思路37.2.2代码实现 35.最大子数组和 35.1…

笔记本电脑为什么可以链接热点,却无法连接WiFi

① 在开始菜单的搜索栏中,输入 cmd 。 ② 右击上方该程序,选择 以管理员身份运行 ③ 输入:nestsh winsock reset ④ 敲击回车,显示如下页面 ⑤ 再输入 ipconfig/flushdns 回车 ⑥ 然后重启电脑,OVER!

98、验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 题解:若要验证是…

Python之父推荐!Star 60k!深入CPython内核:揭秘内部实现细节

都说 Python 是人工智能的“天选”语言,为什么呢? 可能很多读者都知道,Python 的解释器是用 C 语言写的,所以其实我们在谈论 “Python” 的时候,99.9% 的情况说的就是 “CPython”! CPython 是目前最流行的…

SD-WAN组网对比传统组网的优势

随着商业环境的迅速变化,企业对网络连接的需求不断增长。传统组网方案已经难以满足现代企业的需求,而作为一种新兴的网络解决方案,SD-WAN正逐渐受到企业的青睐。那么,SD-WAN究竟在哪些方面优于传统组网方案呢? 灵活性 …

深度探讨网络安全:挑战、防御策略与实战案例

目录 ​编辑 一、引言 二、网络安全的主要挑战 恶意软件与病毒 数据泄露 分布式拒绝服务攻击(DDoS) 内部威胁 三、防御策略与实战案例 恶意软件防护 网络钓鱼防护 数据泄露防护 总结 一、引言 随着信息技术的迅猛发展,网络安全问…

# [0628] Task04 DQN 算法及进阶

easy-rl PDF版本 笔记整理 P6 - P8 joyrl 比对 补充 P7 - P8 相关 代码 整理 待整理 !! 最新版PDF下载 地址:https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用): 链接: https://pan.baidu.com/s/1i…

第二节:如何使用thymeleaf渲染html(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;今天来学习如何使用thymeleaf渲染html。该模板运用不广泛&#xff0c;所以本节内容了解既可。 第一步&#xff1a;创建html文件。 在模板templates目录下创建一个html文件。 编写代码如下&#xff1a; <!DOCTYPE html> <…

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

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

P1114 “非常男女”计划最优解

原题地址 P1114 “非常男女”计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码题解 AC代码&#xff08;1&#xff09; 因为用的是级的算法&#xff0c;所以最后一个 了&#xff0c;这里使用特判来得到的&#xff0c;给你们放一下代码&#xff1a; #include <bi…

《昇思25天学习打卡营第5天|onereal》

ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&#xff1a;Pointw…

49-5 内网渗透 - 服务注册表权限脆弱提权

一、服务注册表权限脆弱提权介绍 Windows操作系统中的注册表存储了每个系统服务的相关条目。注册表使用访问控制列表(ACL)来管理用户对其条目的访问权限。如果注册表的ACL配置不正确,可能导致低权限用户获得对服务注册表的写入权限。攻击者可以利用这一漏洞修改注册表内容,…

【android 9】【input】【9.发送按键事件3——Inputchannel的创建过程】

系列文章 本人系列文章-CSDN博客 目录 系列文章 目录 1.简介 1.1 主要步骤 1.2 时序图 2.源码分析 2.1 WindowManagerImpl的addView 2.2 WindowManagerGlobal的addView 2.3 ViewRootImpl 2.4 getWindowSession 2.5 WMS中的openSession 2.6 Session 2.7 class W 2.…

java周测总结(3)

1、什么是I0流&#xff1f; 是一串流动的字符,从先进先出的方式要求信息的通道。 2、什么是序列化&#xff1f;什么是反序列化&#xff1f; 序例化是将对象的状态存储到特定的存储介质中的过程反序例化是将特定的有合者公质中数据重新构建对象的过程。 3、Java中线程在哪个包下…