信号量(semaphore)

一、信号量简介

       前面介绍的消息队列主要用于传输数据:任务与任务之间、任务与中断之间

       在有些情况下,不需要传输数据,只需要传递状态即可

                • 车开出停车位,你的车可以停进来了

                • 课已经录制完成,你可以进行观看了

1.1 信号量的含义

        信号量是一种实现任务间通信的机制可以实现任务之间的同步临界资源的互斥访问,可以实现对共享资源的有序访问(用于传递状态

共享资源的访问:

※ 案列一:汽车驶入或离开停车位,停车位的个数(计数型信号量)

※案列二:公共电话的使用(二值信号量)

        

任务之间的同步(任务与任务、任务与中断):

        在执行中断服务函数的时候,可以通过释放信号量(不做具体的处理,以提高系统的实时性)来通知某个任务所期待的事件发生了。当退出中断后,通过调度器,同步的任务(做出相应的处理)就会执行

        信号量用于控制共享资源的访问的场景相当于一个上锁机制,只有获得这把锁的钥匙才可以进行下一步操作

Q:既然队列也可以实现同步与互斥那为什么还要信号量?
答:信号量相比队列更节省空间,因为实现同步与互斥不需要传递数据,所以信号量没有队列后面的环形存储区,信号量主要就是依靠计数值uxMessagesWaiting(在队列中表示队列现有消息个数,在信号量中表示有效信号量个数)。

           当计数值 > 0,代表信号量有资源

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

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

        

 信号:通知某个对象

  量:资源的数量:计数值都有限制

         • 限定最大值是1,则是二进制信号量

         • 限定最大值不是1,则是计数值信号量

FreeRTOS中信号量又分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量

总结:信号量是用于传递状态

1.2 队列与信号量的对比

队列

信号量

可以容纳多个数据

创建队列有两部分内存:队列结构体+队列项存储空间

仅存放计数值,无法存放其他数据;

创建信号量,只需分配信号量结构体

写入队列:当队列满时,可阻塞

释放信号量:不可阻塞,计数值++

当计数值为最大值时,返回失败

读取队列:当队列为空时,可阻塞

获取信号量:计数值--

当没有资源时,可阻塞

1.3 二值信号量与计数型信号量的区别

二值信号量计数型信号量
队列长度1大于1
资源初始化0可以根据情况设定

 二、二值信号量

二值信号量的本质:一个队列长度为 1 ,队列项大小为0队列 ,该队列就只有空和满两种情况

        二值信号量通常用于互斥访问或任务同步与互斥信号量(拥有优先级继承)比较类似,但是二值信号量有可能会导致优先级翻转的问题 ,所以二值信号量更适合用于同步(任务与任务、任务与中断)

         同步:所有任务排着队一件件的往后进行,上件事情没有完成,就继续做上件事情,等上件事情完成后才会去做下一件事情

 使用二值信号量的过程创建二值信号量 ——> 释放二值信号量(队满) ——> 获取二值信号量(队空)     

:创建二值信号量时,初始值为0,所以先要释放信号量

2.1 二值信号量相关API函数

头文件:semphr. h

函数

描述

xSemaphoreCreateBinary()

使用动态方式创建二值信号量

xSemaphoreCreateBinaryStatic()

使用静态方式创建二值信号量

xSemaphoreGive()

释放信号量

xSemaphoreGiveFromISR()

在中断中释放信号量

xSemaphoreTake()

获取信号量

xSemaphoreTakeFromISR()

在中断中获取信号量

 注:二值、计数型、互斥信号量释放与获取均用这两个函数 

 2.1.1 动态创建二值信号量:

实质:创建一个长度为1、队列项大小为0的队列

 2.1.2 释放信号量函数:

※ 对于信号量而言,释放不允许设置阻塞时间,如果队列已满,则直接返回

入队方式:向后入队

 2.1.3 获取信号量函数: 

※ 对于信号量而言,获取允许设置阻塞时间,如果队列为空,则可以选择是否进行等待

可以看出:二值信号量的API函数与队列操作的函数相同,区别只是入口参数不同 

 三、计数型信号量

        计数型信号量相当于队列长度大于1 的队列,因此计数型信号量能够容纳多个资源,这在计数型信号量被创建的时候确定

计数型信号量常用于:事件计数、资源管理

注:不同适用场合,信号量创建时的计数值不同

3.1 计数值信号量相关API函数

函数

描述

xSemaphoreCreateCounting()

使用动态方法创建计数型信号量。

xSemaphoreCreateCountingStatic()

使用静态方法创建计数型信号量

uxSemaphoreGetCount()

获取信号量的计数值

             计数型信号量的释放和获取与二值信号量相同 !

3.1.1 动态创建计数值信号量

3.1.2  获取当前计数值

四、互斥信号量(mutex)

4.1 优先级反转:

前面说到,二值信号量用于互斥访问时,会出现优先级反转的情况 

优先级翻转:高优先级的任务反而慢执行,低优先级的任务反而优先执行

        高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转) 

4.2 互斥信号量

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

4.2.1 优先级继承

        优先级继承:暂时提高某个占有某种资源的低优先级任务的优先级,使之与在所有等待该资源的任务中优先级最高那个任务的优先级相等,而当这个低优先级任务执行完毕释放该资源时,优先级重新回到初始设定值

         当任务L获取信号量后,还没来得及释放,就被高优先级的任务抢占,但没有信号量,高优先级任务H就进入阻塞,此时任务L运行,并将任务L的优先级设置为与任务H同等优先级,即使任务M就绪,也不会得到执行,直到L释放信号量,H获取信号量,任务H开始运行

        此时任务H的阻塞时间仅仅是任务L 的执行时间将优先级翻转的危害降到了最低。优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响

总结:

所谓优先级继承,其实就是低优先级任务继承高优先级任务的优先级
发生优先级继承:在高优先级任务获取信号量失败(低优先级任务已经持有信号量)进入阻塞态之前,将持有信号量的低优先级任务的优先级提升

解除优先级继承:在持有信号量的低优先级任务释放信号量的时候,将自己的优先级恢复到初始值(因为已经释放了信号量,完成了任务)

4.3 互斥信号量相关API函数

使用流程:创建互斥信号量 ——> (task获取信号量 ——>(give)释放信号量 

注意:创建互斥信号量时,会主动释放一次信号量

使用互斥信号量:首先将宏configUSE_MUTEXES置1

函数

描述

xSemaphoreCreateMutex()

使用动态方法创建互斥信号量。

xSemaphoreCreateMutexStatic()

使用静态方法创建互斥信号量。

 4.3.1 动态创建互斥信号量

互斥信号量的释放和获取函数与二值信号量相同

        只不过互斥信号量由于涉及到任务优先级继承的性质,而中断不属于任务,没法处理中断由新阿基继承,因此不支持中断中调用

五、递归互斥信号量

5.1 互斥信号的缺点

(1)不能实现由A获取就由A释放

比如:任务A、B互斥访问串口打印资源,假如任务A已经获取,还没释放。此时,任务C偷偷释放,使得资源失去保护,任何任务都可以访问该资源,会发生混乱

(2)死锁

比如:任务A进行两次获取,第二次获取必定失败,导致任务被阻塞,其他任务想要获取,该任务还未释放,导致死锁

5.2 递归互斥信号量

        递归互斥信号量是一种特殊的互斥信号量。已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量(即可以嵌套使用),且次数不限。一个任务获取了多少次递归互斥信号量就必须释放多少次释放之前递归互斥量都处于无效状态其他任务无法获取只有持有递归信号量的任务才能获取和释放

     

  递归互斥信号量不能在中断函数中使用 

5.3 递归互斥信号量相关API函数

5.3.1 动态创建

使用条件:configSUPPORT_DYNAMIC_ALLOCATION 和 configUSE_RECURSIVE_mutexes 都必须在 FreeRTOSConfig.h 中定义为 1

SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )

返回值:

成功:返回创建的互斥锁的句柄

失败:返回 NULL

 SemaphoreHandle_t xMutex;void vATask( void * pvParameters ){Create a recursive mutex.xMutex = xSemaphoreCreateRecursiveMutex();if( xMutex != NULL ){/* The recursive mutex was created successfully andcan now be used. */}}

注:

使用流程:创建递归互斥信号量 ——> (task获取信号量 ——>(give)释放信号量 

注意:创建递归互斥信号量时,会主动释放一次信号量

 

5.3.2 获取递归互斥信号量

使用条件:configUSE_RECURSIVE_MUTEXES 设置为 1

xSemaphoreTakeRecursive( SemaphoreHandle_t xMutex,TickType_t xTicksToWait );

 SemaphoreHandle_t xMutex = NULL;// A task that creates a mutex.void vATask( void * pvParameters ){// Create the mutex to guard a shared resource.xMutex = xSemaphoreCreateRecursiveMutex();}// A task that uses the mutex.void vAnotherTask( void * pvParameters ){// ... Do other things.if( xMutex != NULL ){// See if we can obtain the mutex.  If the mutex is not available// wait 10 ticks to see if it becomes free.    if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ){xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );xSemaphoreGiveRecursive( xMutex );xSemaphoreGiveRecursive( xMutex );xSemaphoreGiveRecursive( xMutex );// Now the mutex can be taken by other tasks.}else{// We could not obtain the mutex and can therefore not access// the shared resource safely.}}}

 5.3.3 释放递归互斥信号量

使用条件:将 configUSE_RECURSIVE_MUTEXES 设置为 1

xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )

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

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

相关文章

解决前后端同一个端口跨域问题

前端起了一个代理 如果url是api开头的自动代理访问8080端口(解决前后端端口不一致要么是前端代理,要么是后端加过滤器) proxy:{/api:{target:http://localhost:8080,changeOrigin : true,// 替换去掉路径上的api// rewrite:(path)>path.r…

常规情况与opencv图像中,计算直线与矩形框的交点

文章目录 1、普通方式1.1、普通计算过程1.2、优化方式 2、图像中的情况2.1、常规处理2.2、opencv中的处理2.2.1、cv::clipLine函数2.2.2、测试代码2.2.3、测试结果 1、普通方式 已知矩形框左上(x1,y1)、右下(x2,y2)点,直线方程 y kxb,求交点…

tinyshop商城学习

1、使用badboy屏幕录制工具,获得服装购物业务的结果,生成.jmx文件 2、在JMeter中新建线程组,导入.jmx文件 3、完成进入商城,登录,服装页面进入,随机选择服装,添加购物车,开始结算&…

SpringBoot整合Dubbo的快速使用教程

目录 一、什么是Dubbo? 二、SpringBoot整合Dubbo 1、父工程引入依赖 2、各个Dubbo服务子模块引入依赖 3、服务提供者 (1)启动类添加注解EnableDubbo (2)服务类添加注解DubboService (3)配置文件…

Patch SCN使用说明---惜分飞

软件说明 该软件是惜分飞(https://www.xifenfei.com)开发,仅用来查看和修改Oracle数据库SCN(System Change Number),主要使用在数据库因为某种原因导致无法正常启动的情况下使用该工具进行解决.特别是Oracle新版本中使用隐含参数,event,orad…

Java核心 - 泛型详解

文章目录 一、概述1、什么是泛型2、用泛型最直接的优点3、分类 二、泛型详解1、泛型类(1)概述(2)代码实例 2、泛型派生类(1)概述(2)代码实例(3)扩展&#xff…

10元 DIY 一个柔性灯丝氛围灯

之前TikTok上特别火的线性氛围灯Augelight刚出来的时候一度卖到80多美金,国内1688也能到400多人民币。 随着各路国内厂商和DIY创客的跟进,功能变多的同时价格一路下滑,虽然有的质感的确感人,但是便宜啊。 甚至关注的up有把成本搞到…

【24年一博研讨会总结】BJ0705

1.工艺边据PCB边缘 >5mm. 2.IPC-A-600G Pitch < 1.25mm H<0.025mm,小于0.4mm,取消丝印框&#xff0c;防止锡膏不匀虚焊&#xff1b; 3.表面镀金与镍厚度 金厚度 um镍厚度 um0.0192.7830.0213.3610.0453.6640.0314.378 4.多层板&#xff0c;层间距>20mil 可以认…

Ubuntu系统复制文件到共享文件夹出错

1、问题描述 Ubuntu系统复制文件到共享文件夹时&#xff0c;出现拼接文件时出错&#xff1a;输入/输出错误。 使用cp命令&#xff1a; cp -Rf XXX YYY 也是出错&#xff1a; cp: 写入 xxx 出错: 输入/输出错误 2、查看磁盘空间 查看磁盘空间&#xff0c;显示空间还有剩余…

安乃达:看不懂的募资

不好玩啊&#xff0c;高标接连被S&#xff0c;市场激进资金找到了新股作为抱团方向。 首日大涨超100%&#xff0c;两日涨幅133%&#xff0c;今天果不其然被电风扇刮走了&#xff0c;今天我们聊聊新加入A股大本营的公司——安乃达。 首先&#xff0c;安乃达是国内直驱轮毂电机头…

零基础学python(一)

1. 匿名函数 常规函数&#xff1a; def fun(x, y):return x y 匿名函数&#xff1a; # lambda 空格后面是函数入参&#xff0c;冒号后面写函数体/函数逻辑 a lambda x,y: x y print(a(2,3)) 匿名函数/lambda函数的最大优点就是快速定义函数&#xff0c;使代码更精简。 …

【数据结构】(6.3)堆的应用——堆排序(C语言)

系列文章目录 文章目录 系列文章目录前言1. 堆排序的基础知识2. 堆排序详解2.1 堆排序整体思路2.2 思路详解2.2.1 建堆2.2.2 堆排序完整代码2.2.3 输出数据 3. 时间复杂度分析 前言 1. 堆排序的基础知识 堆排序&#xff08;Heap Sort&#xff09;就是对直接选择排序的一种改进…

04通俗理解自注意力机制(self-attention)

04浅谈自注意力机制&#xff08;self-attention&#xff09; 1. 基本概念 注意力机制 是Transformer模型的核心。它的作用是让模型能够“关注”输入数据的不同部分&#xff0c;而不是一次只处理一个词。比如&#xff0c;当模型在处理一句话时&#xff0c;它可以同时考虑句子中…

2024攻防演练:亚信安全新一代WAF,关键时刻守护先锋

实网攻防 网络安全如同一面坚固的盾牌&#xff0c;保护着我们的信息资产免受无孔不入的威胁。而其中&#xff0c;WAF就像网络安全的守门员&#xff0c;关键时刻挺身而出&#xff0c;为您的企业筑起一道坚实的防线。 攻防不对等 防守方实时应答压力山大 在攻防对抗中&#xf…

day04-matplotlib入门

matplotlib Matplotlib 提供了一个套面向绘图对象编程的 API接口 是一款用于数据可视化的 Python 软件包&#xff0c;支持跨平台运行 它能够根据 NumPyndarray 数组来绘制 2D(3D) 图像&#xff0c;它使用简单、代码清晰易懂&#xff0c;深受广大技术爱好 者喜爱。 实列&…

Django学习第五天

启动项目命令 python manage.py runserver 图像验证码生成随机字母或者数字 import random from PIL import Image, ImageDraw, ImageFont, ImageFilterdef check_code(width120, height40, char_length5, font_fileZixunHappyBold.ttf, font_size28):code []img Image.new…

Spring框架Mvc(2)

1.传递数组 代码示例 结果 2.集合参数存储并进行存储类似集合类 代码示例 postman进行测试 &#xff0c;测试结果 3.用Json来对其进行数据的传递 &#xff08;1&#xff09;Json是一个经常使用的用来表示对象的字符串 &#xff08;2&#xff09;Json字符串在字符串和对象…

图文识别0难度上手~基于飞浆对pdf简易ocr并转txt

前言 本篇pdf适用windows对视觉识别0基础的的纯小白用户。大佬请绕道~~ 注意&#xff1a; 本项目pdf的ocr对于表格、画图文字&#xff0c;水印等干扰没做任何处理&#xff0c;因此希望各位使用该功能的pdf尽量不要含有这些干扰项&#xff0c;以免影响翻译效果。 流程 1.构建…

【c语言】轻松拿捏自定义类型

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C语言 目录 前言 一、结构体 1.结构体类型的定义和使用 1.1 结构体类型声明 1.2 结构体变量的创建和初始化 1.3 结构体变量成员的访问 1.4 结构体的特殊声…

三万字带你一遍跑通uer

三万字带你一遍跑通uer 参考文档 今天给大家介绍个非常强大的项目uer&#xff0c;集成了许多可以做自然语言的东西&#xff0c;效果的话也非常好&#xff0c;很适合企业级的应用&#xff01; 1. 先将项目uer从github拉取下来&#xff08;zip或git都ok&#xff09; 2. 用pycha…