当前位置: 首页 > news >正文

本篇5K,立志最细,FreeRtos中的信号量Semaphore教程详解!!!

                        前言:本篇教程,参考韦东山,开发文档,连接放在最后   

目录

Semaphore基本概念

二值信号量(Binary Semaphore)

计数信号量(Couting Semaphore)

互斥信号量(Mutex)

信号量释放和使用函数


Semaphore基本概念

        信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务之间的同步或者互斥访问,主要分为,二值信号量(Binary Semaphore)计数信号量(Couting Semaphore)互斥信号量(Mutex)。

        与queue传输数据不同的是Semaphore利用本身信号量计数值用来传递决定Task能不能进行访问的状态,同时用这种状态来完成,Task的同步,互斥,限制访问资源Task数量。

        信号量的API函数实际上使用的都是宏,使用来自现有的队列机制,二者也是有相似的地方的。

FreeRtos机制队列(Queue)信号量(Semaphore)
容纳数据可以容纳多个数据只能存放信号量计数值,对其进行操作
写操作Queue没有空间写数据可以阻塞计数值最大时,返回不进入阻塞状态
读操作Queue中没有数据可以阻塞没有信号量时可以阻塞

        表格里面需要注意的是,信号量(Semaphore)在进行释放的时候,如果达到规定值,这个时候是没有阻塞状态的,只有等待信号量的时候有阻塞状态

二值信号量(Binary Semaphore)

        这种类型信号量,调用函数创建,信号量计数值默认初始化为0,同时计数值,取值只有0 或1 ,通常用来实现Task之间的互斥。

SemaphoreHandle_t xSemaphoreCreateBinary( void ); //动态创建
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer );//静态创建 需要结构体类型存储信号量

        同样的Semaphore(信号量)的创建也分为动态创建和静态创建,区别也是静态创建需要结构体来存储数据。需要注意,这里在创建使用的时候,同时需要声明句柄,来创建,和后续通过句柄来完成对信号量的释放和使用操作。

static SemaphoreHandle_t Binary_Semaphore_Handle;//创建句柄承接创建函数的返回值
Binary_Semaphore_Handle = xSemaphoreCreateBinary();//使用函数创建二进制信号量

计数信号量(Couting Semaphore)

        技术型信号量最大的特定是,创建的时候可以确定,信号量最大值,与初始值,计数信号量,通常用来限制访问互斥资源的数量。

SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);//  uxMaxCount: 信号量最大值  uxInitialCount 信号量初始值
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer );

        同样的计数型信号量的创建也分为动态创建和静态创建,区别也是静态创建需要创建存放信号量的数据结构。

static SemaphoreHandle_t counting_Semaphore_Handle; //创建句柄
counting_Semaphore_Handle = xSemaphoreCreateCounting(3,2);//信号量最大值为3,初始值为2的计数型信号量

        这里调用需要注意的是,最大值是不能小于信号量的初始值的。

信号量二进制信号量量计数型信号量
动态创建xSemaphoreCreateBinary xSemaphoreCreateCounting
静态创建xSemaphoreCreateBinaryStaticxSemaphoreCreateCountingStatic
信号量初始值二进制信号量初始值为0计数型信号量初始值自己设定
释放申请删除操作相同操作相同

优先级反转问题

        优先级反转指的是,高优先级任务因为等待低优先级任务释放信号量进入阻塞,低优先级任务被中优先级任务抢占了CPU,没有办法执行任务释放,信号量导致了整体的系统延迟的情况。

        任务A(高优先级)

        任务B(低优先级)

        任务C(中优先级)

        任务B持有资源:任务B(低优先级)首先获得了一个共享资源,比如某个互斥信号量,用于保护一个共享数据。

        任务A请求资源:此时,任务A(高优先级)需要使用相同的共享资源,但由于任务B正在使用该资源,任务A必须等待任务B释放互斥信号量。于是,任务A进入阻塞状态,等待资源变得可用。

        任务C抢占CPU:在任务A等待资源的同时,任务C(中优先级)不依赖该资源,但由于它的优先级高于任务B,它会在任务A和任务B之间获得CPU的执行机会,抢占任务B的CPU时间。

        上面这种情况就会导致了,优先级反转问题的产生。

        使用二进制信号量在多任务系统访问资源中,有概率会出现这个问题,需要防止这个问题的出现,当创建Task的时候可以尽量避免,中优先级的任务创建,或者使用互斥信号量后者的优先级继承问题可以有效的避免,优先级反转问题的出现。

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "stdio.h"// 任务句柄
TaskHandle_t xHighPriorityTaskHandle, xMediumPriorityTaskHandle, xLowPriorityTaskHandle;// 信号量句柄
SemaphoreHandle_t xMutex;// 低优先级任务,持有共享资源
void vLowPriorityTask(void *pvParameters) {// 获取互斥信号量,模拟持有共享资源xSemaphoreTake(xMutex, portMAX_DELAY);printf("Low Priority Task: Obtained the mutex and using the resource.\n");// 模拟任务占用资源较长时间vTaskDelay(pdMS_TO_TICKS(2000));printf("Low Priority Task: Releasing the mutex.\n");// 释放互斥信号量xSemaphoreGive(xMutex);// 任务结束vTaskDelete(NULL);
}// 高优先级任务,等待获取共享资源
void vHighPriorityTask(void *pvParameters) {vTaskDelay(pdMS_TO_TICKS(500)); // 延迟以确保低优先级任务先执行printf("High Priority Task: Attempting to obtain the mutex...\n");// 试图获取互斥信号量xSemaphoreTake(xMutex, portMAX_DELAY);printf("High Priority Task: Obtained the mutex and using the resource.\n");// 模拟资源使用时间vTaskDelay(pdMS_TO_TICKS(1000));// 释放互斥信号量xSemaphoreGive(xMutex);printf("High Priority Task: Released the mutex.\n");// 任务结束vTaskDelete(NULL);
}// 中优先级任务,不需要共享资源,只是执行一段时间
void vMediumPriorityTask(void *pvParameters) {for (int i = 0; i < 5; i++) {printf("Medium Priority Task: Executing...\n");vTaskDelay(pdMS_TO_TICKS(500)); // 模拟占用CPU时间}// 任务结束vTaskDelete(NULL);
}int main(void) {// 创建互斥信号量xMutex = xSemaphoreCreateMutex();if (xMutex != NULL) {// 创建低优先级任务,优先级为1xTaskCreate(vLowPriorityTask, "Low Priority Task", configMINIMAL_STACK_SIZE, NULL, 1, &xLowPriorityTaskHandle);// 创建高优先级任务,优先级为3xTaskCreate(vHighPriorityTask, "High Priority Task", configMINIMAL_STACK_SIZE, NULL, 3, &xHighPriorityTaskHandle);// 创建中优先级任务,优先级为2xTaskCreate(vMediumPriorityTask, "Medium Priority Task", configMINIMAL_STACK_SIZE, NULL, 2, &xMediumPriorityTaskHandle);// 启动调度器vTaskStartScheduler();}// 如果代码运行到这里,说明调度器未能启动for(;;);
}

互斥信号量(Mutex)

        互斥信号量(Mutex)是信号量的一种特殊类型,专门用来保护临界资源,确保只有一个任务可以访问该资源,特别的是互斥信号量拥有优先级继承机制,这种机制是二进制信号量和计数信号量没有的

        优先级继承机制特点在于,当低优先级人物持有互斥信号量,同时高优先级任务等待获取该信号量,低优先级任务会短暂提升自身优先级与高优先级任务优先级相同,直到释放互斥信号量,自身优先级会被取消,这个机制来保证因为任务优先级导致释放资源延迟程序的情况。

        通常用于保护共享资源,防止任务并发访问。特别适合用于需要防止数据竞争的场景,并且系统中可能存在优先级反转问题的情况。

        这种优先级集成机制,可以有效的避免优先级反转问题造成的,Task被阻止或者严重延迟。

SemaphoreHandle_t xSemaphoreCreateMutex( void );
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer );

        上面是创建Mutex的原型函数,同样的静态创建需要定义结构体。

SemaphoreHandle_t Mutex_Handle; //声明句柄
Mutex_Handle =  xSemaphoreCreateMutex();//创建Mutex

信号量操作函数

        上文提及了,信号量不同的类型,当创建完信号量之后还要通过对信号量进行释放,使用,删除来完成特定任务。

BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore );//参数xSemaphore信号量句柄
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait);//xTicksToWait 0:不阻塞, portMAX_DELAY: 一直阻塞直到成功 

        这里需要注意的是使用信号量函数,多一个参数可选,可以选择阻塞等待信号量不等待信号量,如果是在中断中使用则是下面的函数。

BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken);
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken);

        需要注意的是,在二进制信号量中,多次使用释放信号量函数,二进制信号量的值依旧是1,不会因为多次调用函数,从而导致信号量值的提高。

        创建的信号量,在不需要的时候,同样的可以通过函数来删除,这里函数的参数是需要删除信号量的句柄。

void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );//里面的参数填写句柄

                                        欢迎指正,希望对你,有所帮助!!!

[9-2-2]_信号量实验_优先级反转_哔哩哔哩_bilibili

相关文章:

本篇5K,立志最细,FreeRtos中的信号量Semaphore教程详解!!!

前言&#xff1a;本篇教程&#xff0c;参考韦东山&#xff0c;开发文档&#xff0c;连接放在最后 目录 Semaphore基本概念 二值信号量&#xff08;Binary Semaphore&#xff09; 计数信号量&#xff08;Couting Semaphore&#xff09; 互斥信号量&#xff08;Mutex&…...

【Postman】接口测试工具使用

干就完啦 Postman发送get请求案例1&#xff1a; Postman发送post请求案例2 Postman发送其他请求Postman测试实战 学习目标&#xff1a;能够使用Postman发送get/post/put/delete请求并获取响应结果 Postman发送get请求 首先postman是一款接口调试工具&#xff0c;支持win&…...

springboot 整合 rabbitMQ(1)

目录 一、MQ概述 二、MQ的优势和劣势 三、常见的MQ产品 RabbitMQ使用步骤 第一步&#xff1a;确保rabbitmq启动并且可以访问15672 第二步&#xff1a;导入依赖 第三步&#xff1a;配置 auto自动确认 manual手工确认&#xff08;推荐使用&#xff01;可以防止消息丢失&a…...

Appium Device Farm安装教程

环境要求&#xff1a;Appium version ≥ 2.4.X 安装appium npm install -g appium2.11.3 如果安装提示如下问题 npm error code EEXIST npm error syscall rename npm error path /Users/wan/.npm/_cacache/tmp/d5787519 npm error dest /Users/wan/.npm/_cacache/content-…...

异常、基类

异常 人生和世界总是充满着意外&#xff0c;争议、冲突和战争似乎是人类必然经历的过程。程序执行也有不满的时候。 不同编程语言的异常 Ada/Modula-3是早期引入异常处理的语言。 C语言没有标准意义的异常&#xff0c;使用goto或setjmp模拟错误或异常发生时的处理流程。 C/Java…...

VScode 自定义代码配色方案

vscode是一款高度自定义配置的编辑器, 我们来看看如何使用它自定义配色吧 首先自定义代码配色是什么呢? 看看我的代码界面 简而言之, 就是给你的代码的不同语义(类名, 函数名, 关键字, 变量)等设置不同的颜色, 使得代码的可读性变强. 其实很多主题已经给出了定制好的配色方案…...

MuMu模拟器12 KitsumeMask安装教程

这里是引用"> 在MuMu模拟器上安装KitsumeMask的时候遇到安装失败的情况。 一、下载APK安装包 如果你没有apk安装包可以通过下面的百度网盘进行下载 通过网盘分享的文件:KitsumeMask 链接: https://pan.baidu.com/s/1yeq3I6BsUD7J6uI-bnk-Vw?pwd=7n3v 提取码: 7n3v 二…...

Perforce静态分析工具2024.2新增功能:Helix QAC全新CI/CD集成支持、Klocwork分析引擎改进和安全增强

Perforce Helix QAC和Klocwork的最新版本对静态分析工具进行了重大改进&#xff0c;通过尽早修复错误、降低开发成本和加快发布速度&#xff0c;使开发团队实现左移。 本文中&#xff0c;我们将概述2024.2版本的新特性和新功能。 CI/CD和左移以实现持续合规性 现代软件开发实…...

太阳能电池特性及其应用

中南民族大学-通信工程2024-大学物理下实验 目录 代码实现结果显示 &#x1f6e0;工具使用 MarsCode&#xff08;插件&#xff0c;集成在PyCharm&#xff09;&#xff1b; python编程&#xff08;豆包AI智能体&#xff09; &#x1f4bb;编程改进 此处是用「Matplotlib」来作图…...

日语学习零基础生活日语口语柯桥外语学校|股票用日语怎么说?

在日语中&#xff0c;“股票”可以说&#xff1a; • 株&#xff08;かぶ&#xff09; 这是最常用的表达方式&#xff0c;直接表示“股票”。 例如&#xff1a; 株を買う - 买股票 株を売る - 卖股票 • 株式&#xff08;かぶしき&#xff09; 这个词也是“股票”的意…...

第2关:寻找一个序列中的第K小的元素(即第k小元问题)

[TOC]寻找一个序列中的第K小的元素&#xff08;即第k小元问题&#xff09; 对于给定的含有n(n<100)元素的无序序列&#xff0c;求这个序列中第k&#xff08;1≤k≤n&#xff09;小的元素。 任务描述 本关任务&#xff1a;编写一个能计算数组中的第k小的元素的小程序。 相关…...

docker 搭建 vue3 + vite

vue3发布了,今天就分享一下我使用docker 搭建 vue3 vite 开发环境。至于为什么使用docker搭建&#xff0c;因为多版本可以快速切换&#xff0c;和本地环境避免冲突。好了话不多说我们开始吧。 1. 准备资料 Docker Desktop wsl2 ubuntu 下载地址 : https://www.docker.…...

【网易云音乐】--源代码分享

最近写了一个网易云音乐的音乐实现部分&#xff0c;是通过JavaScript和jQuery实现的&#xff0c;具体效果大家可以参照下面的视频 源代码分享 - git地址: 网易云音乐源代码 下面将着重讲解一下音乐实现部分 视频有点模糊&#xff0c;不好意思&#xff0c;在b站上添加视频的时候…...

股市大涨下的会展业创新者

近期&#xff0c;股市涨势强劲有力&#xff0c;各大指数普遍上扬&#xff0c;市场活力空前。与此同时&#xff0c;伴随全球经济逐步复苏及会展行业不断发展&#xff0c;上市展览公司机遇与挑战并存。国内外市场需求持续增长拓展了广阔发展空间&#xff0c;但同时行业竞争愈发激…...

工具篇-完整的 Git 项目管理工具教程(在命令框中使用 Git、在 IDEA 中使用 Git)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Git 概述 2.0 Git 的安装和配置 3.0 获取本地仓库 3.1 基础操作指令 3.2 分支 4.0 Git 远程仓库 4.1 创建远程仓库 4.2 配置 SSH 公钥 4.3 操作远程仓库 5.0 使用…...

关于Amazon Linux 2023的版本及包管理器

在亚马逊上创建EC2实例时&#xff0c;会看到有一个Amazon Linux镜像。 那这个镜像与其他Linux有什么关系和区别呢&#xff1f; 网站是介绍&#xff1a;Amazon Linux 2023 是基于 Linux 的现代化通用操作系统&#xff0c;提供 5 年的长期支持。它针对 AWS 进行了优化&#xff0…...

Java面向对象编程--高级

目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习&#xff0c;测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…...

Vert.x,Web - 静态资源/模板

静态资源 Vert.x-Web带有开箱即用的处理器(StaticHandler)&#xff0c;用于处理静态Web资源(.html, .css, .js, …)&#xff0c; 因此可以非常轻松地编写静态Web服务器。 默认静态文件目录为类路径下的webroot目录&#xff0c;对于maven的项目&#xff0c;按规范放在src/main/…...

OpenAI今天Open了一下:开源多智能体框架Swarm

来源 | 机器之心 毫无疑问&#xff0c;多智能体肯定是 OpenAI 未来重要的研究方向之一&#xff0c;前些天 OpenAI 著名研究科学家 Noam Brown还在 X 上为 OpenAI 正在组建的一个新的多智能体研究团队招募机器学习工程师。 就在几个小时前&#xff0c;这个或许还没有组建完成的新…...

车辆重识别(2021NIPS无分类器扩散指南)论文阅读2024/10/08

[1] CLASSIFIER-FREE DIFFUSION GUIDANCE&#xff08;无分类器扩散指导&#xff09; (NIPS 2021) 作者&#xff1a;Jonathan Ho & Tim Salimans 单位&#xff1a;Google Research, Brain team&#xff08;谷歌团队&#xff09; 摘要&#xff1a; 分类器指导是最近引入的一…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...