十五、信号量

1、概述

(1)前面介绍的队列(queue)可以用于传输数据:在任务之间、任务和中断之间。

(2)有些时候我们只需要传递状态,并不需要传递具体的信息,比如:

  • 我的事做完了,通知一下你。
  • 卖包子了、卖包子了,做好了1个包子!做好了2个包子!做好了3个包子!
  • 这个停车位我占了,你们只能等着。

(3)以上情况可以使用信号量(semaphore),它更节省内存。

(4)主要涉及内容

  • 怎么创建、删除信号量?
  • 怎么发送、获取信号量?
  • 什么是计数型信号量?什么是二进制信号量?

2、信号量的特性

2.1、信号量的常规操作

(1)什么是信号量?信号量这个名字很恰当:

  • 信号:起通知的作用。
  • 量:可以用来表示资源的数量。(当“量”没有限制时,它就是"计数型信号量"(Counting Semaphores),当"量"只有0、1两个取值时,它就是"二进制信号量"(Binary Semaphores)。)
  • 支持的动作:"give"出资源,计数值加1;"take"获资源,计数值减1。

(2)计数型信号的典型场景:

  • 计数:事件产生时"give"信号量,让计数值加1;处理事件时要先"take"信号量,就是获取信号量,让计数值减1。(give:给;take:取)
  • 资源管理:要想访问资源需要先"take"信号量,让计数值减1;用完资源后"give"信号量,让计数值加1。

(3)信号量的"give"、"take"双方并不需要相同,可以用于生产者-消费者场合:

  • 生产者为任务A、B,消费者为任务C、D。
  • 一开始信号量的计数值为0,如果任务C、D想获得信号量,会有两种结果:
    • 阻塞:买不到东西咱就等等吧,可以定个闹钟(超时时间)
    • 即刻返回失败:不等
  • 任务A、B可以生产资源,就是让信号量的计数值增加1,并且把等待这个资源的顾客唤醒。
  • 唤醒谁?谁优先级高就唤醒谁,如果大家优先级一样就唤醒等待时间最长的人。

(4)计数型信号量的取值范围是0~最大值。

  • 信号量用来表示资源数量,不能是负值。       
  • 创建信号量时就指定的最大值。  

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

2.2、信号量跟队列的对比

差异列表如下:

队列信号量

可以容纳多个数据,

创建队列时有两部分内存:队列结构体、存储数据的空间

只有计数值,无法容纳其他数据。
创建信号量时,只需要分配信号量结构体
生产者:没有空间存入数据时可以阻塞

生产者:永远不阻塞,计数值已经达到最大时

返回失败

消费者:没有数据时可以阻塞消费者:没有资源时可以阻塞

2.3、两种信号量的对比

(1)信号量的计数值都有限制:限定了最大值。如果最大值被限定为1,那么它就是二进制信号量;如果最大值不是1,它就是计数型信号量。

(2)差异列表如下:

二进制信号量计数型信号量
被创建时初始值为0被创建时初始值可以设定
其他操作是一样的其他操作是一样的

3、信号量函数

(1)使用信号量时,先创建、然后去添加资源、获取资源。使用句柄来表示一个信号量。

3.1、创建

(1)使用信号量之前,要先创建,得到一个句柄;使用信号量时,要使用句柄来表明使用哪个信号量。

(2)对于二进制信号量、计数型信号量,它们的创建函数不一样:

二进制信号量计数型信号量
动态创建xSemaphoreCreateBinary
计数值初始值为0
xSemaphoreCreateCounting
vSemaphoreCreateBinary(过时了)
计数值初始值为1
静态创建xSemaphoreCreateBinaryStaticxSemaphoreCreateCountingStatic

(3)创建二进制信号量的函数原型如下:

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


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

(4)创建计数型信号量的函数原型如下:

/* 创建一个计数型信号量,返回它的句柄。
 * 此函数内部会分配信号量结构体
 * uxMaxCount: 最大计数值
 * uxInitialCount: 初始计数值
 * 返回值: 返回句柄,非NULL表示成功
 */
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, 
                                            UBaseType_t uxInitialCount );

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

3.2、删除

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

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

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

3.3、give/take

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

在任务中使用在ISR中使用
givexSemaphoreGivexSemaphoreGiveFromISR
takexSemaphoreTakexSemaphoreTakeFromISR

(2)xSemaphoreGive函数原型如下:

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );

(3)xSemaphoreGive函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,释放哪个信号量
返回值pdTRUE表示成功,
如果二进制信号量的计数值已经是1,再次调用此函数则返回失败;
如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败

(4)xSemaphoreGiveFromISR的函数原型如下:

BaseType_t xSemaphoreGiveFromISR(
        SemaphoreHandle_t xSemaphore,
        BaseType_t *pxHigherPriorityTaskWoken
);

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

参数说明
xSemaphore信号量句柄,释放哪个信号量
pxHigherPriorityTaskWoken如果释放信号量导致更高优先级的任务变为了就绪态,
则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE表示成功,
如果二进制信号量的计数值已经是1,再次调用此函数则返回失败;
如果计数型信号量的计数值已经是最大值,再次调用此函数则返回失败

(6)xSemaphoreTake的函数原型如下:

BaseType_t xSemaphoreTake(
            SemaphoreHandle_t xSemaphore,
            TickType_t xTicksToWait
);

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

参数说明
xSemaphore信号量句柄,获取哪个信号量
xTicksToWait如果无法马上获得信号量,阻塞一会:
0:不阻塞,马上返回
portMAX_DELAY: 一直阻塞直到成功
其他值: 阻塞的Tick个数,可以使用 pdMS_TO_TICKS() 来指定阻塞时间为若干
ms
返回值pdTRUE表示成功

(8)xSemaphoreTakeFromISR的函数原型如下:

BaseType_t xSemaphoreTakeFromISR(
            SemaphoreHandle_t xSemaphore,
            BaseType_t *pxHigherPriorityTaskWoken
);

(9)xSemaphoreTakeFromISR函数的参数与返回值列表如下:

参数说明
xSemaphore信号量句柄,获取哪个信号量
pxHigherPriorityTaskWoken如果获取信号量导致更高优先级的任务变为了就绪态,
则*pxHigherPriorityTaskWoken = pdTRUE
返回值pdTRUE表示成功

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件过程模型分析与适应场景: 瀑布、原型、增量、螺旋、组件化和统一模型简介

软件过程模型: 瀑布模型 ​ 有很强的前后关联性,前一阶段的输出是后一阶段的输入,而且不可回溯性。 适应场景: ​ 软件开发人员经验丰富​ 需求变化少,变更少,可以一次性获取全部需求​ 项目风险低&…

专用博客模板

【点我-这里送书】 本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的…

Docker实用篇

Docker实用篇 0.学习目标 1.初识Docker 1.1.什么是Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署…

六:ffmpe音频参数的使用

-aframes 设置要输出的音频帧数 -b:a 设置音频码率 -ar 设定采样率 -ac 设定声音的Channel数 -acodec 设定声音的编解码器,如果用copy标识原始编解码数据必须被copy -an 不处理音频 -af 音频过滤器 写笔记前查阅了其它说明, -aframes:等价…

海康威视嵌入式软件一面(技术面)

海康威视技术面试大部分都是基础问题和牛客上的问题,最后还有手撕代码部分也是牛客原题,总体中等偏难。 一、问答题 1.什么是野指针,野指针如何形成 【C语言基础】野指针与空指针_野指针和空指针-CSDN博客 2.const和static作用和区别 sta…

微信小程序隐私政策不合规,应当由用户自主阅读后自行选择是否同意隐私政策协议,不得默认强制用户同意

小程序隐私政策不合规,默认自动同意《用户服务协议》及《隐私政策》,应当由用户自主阅读后自行选择是否同意隐私政策协议,不得默认强制用户同意,请整改后再重新提交。 把 登录代表同意《用户协议》和《隐私政策》 改为 同意《用…

Socket编程

1. 什么是Socket 为了应用层和传输层能够交互,操作系统提供一些API给应用层,这些API可以把应用层的数据交给传输层,而这些API就是socket。传输层中有很多协议,其中知名的就是TCP和UDP,因此操作系统提供了两个版本的AP…

Windows10腾讯文档下载和安装

文章目录 Windows10腾讯文档下载和安装官网下载执行安装 Windows10腾讯文档下载和安装 官网下载 官网 下载后: 执行安装 找到下载目录 安装后打开 扫描登录即可

Clickhouse学习笔记(9)—— 语法优化

ClickHouse 的 SQL 优化规则是基于 RBO(Rule Based Optimization)实现的 官方数据集的使用 为了方便测试CK的语法优化规则,尝试使用官方提供的数据集; 需要使用的数据集是visits_v1和hints_v1: Anonymized Web Analytics Data …

【大模型】大语言模型语料下载

文章目录 概述Hugging Faceobs操作git-lfs例子RedPajama-Data-1TSlimPajama-627B/git clone续传 数据格式参考资料 概述 大模型训练中语料是非常重要的,目前公网上有各种各样的语料可以供下载,但是不可能每个用户、每次训练任务都通过公网去拉取语料&am…

SparkSQL之Rule体系

在Unresolved LogicalPlan逻辑算子树的操作(如绑定、解析、优化等)中,主要方法都是基于规则(Rule)的,通过Scala语言模式匹配机制(Pattern-match)进行树结构的转换或节点改写。Rule是…

践行“微”使命——建行江门市分行大力发展普惠金融支持小微企业

促进小微企业发展是保持国民经济高质量发展的重要基础。建行广东省江门市分行立足当地特色产业之需,以金融活水润泽侨乡众多小微企业,携手共赴美好未来。 双向奔赴,添翼高企发展 江门开平水口镇是全国三大水暖卫浴生产基地之一,…

PDF文件编辑器有哪些?10 个适用的PDF 编辑器推荐!

PDF 编辑器始终配备简单的界面以及高效管理工作所需的所有功能。 那么如何选择合适的版本呢?在线工具还是离线工具更好? 为了帮助您回答这些问题,我将通过多次深入的测试来详细回顾十大免费编辑器。现在让我们来探索一下吧! 10 …

UDP协议

1.UDP协议的特点 无连接:不需要双方建立连接,直接就可以发送,就类似发短信,不需要知道对方是否在线,直接发送不可靠传输:无法知道对方是否有收到信息面向数据报:发送消息是以数据报尾单位全双工…

游戏交易平台系统源码下载 网络游戏币、装备、账号、道具等交易网站源码

最新仿7881游戏交易平台系统源码下载网络游戏币、装备、账号、道具等交易网站源码 下载地址:https://bbs.csdn.net/topics/617562568

数据结构与算法之排序: Leetcode 21. 合并两个有序链表 (Typescript版)

合并两个有序链表 https://leetcode.cn/problems/merge-two-sorted-lists/ 描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 …

最详细ChatGPT+AI绘画+企业知识库+视频去水印系统源码搭建流程,手把手教你搭建

一、系统介绍 这款源码搭载了强大的AI问答功能,是基于目前最强大AI大语言模型ChatGPT进行开发的Ai智能问答系统,并使用stablediffusion加最新的comfyui作为底层技术的绘画系统,使用comfyui的api接口,可以更灵活的定制自己的绘画工作流&#…

亲身体验告诉你:亚马逊云科技海外服务器是否值得一试?

前言 在当今数字化时代,云计算已经成为企业和个人发展的重要支撑。亚马逊云科技作为全球领先的云计算服务提供商,其海外服务器备受瞩目。然而,对于一些用户来说,是否值得一试亚马逊云科技的海外服务器仍然是一个疑问。本文将通过亲…

02. Python基础数据类型

1、前言 前面我们介绍了认识了Python以及Python的基础环境搭建,今天我们介绍下Python的一些基础语法。 2、Python基础 2.1、输入输出 2.1.1、输出 print() 用于输出指定的文字,括号中的为输出的字符串。print()也可以同时接收多个字符串,…

CHM Viewer Star 6.3.2(CHM文件阅读)

CHM Viewer Star 是一款适用于 Mac 平台的 CHM 文件阅读器软件,支持本地和远程 CHM 文件的打开和查看。它提供了直观易用的界面设计,支持多种浏览模式,如书籍模式、缩略图模式和文本模式等,并提供了丰富的功能和工具,如…