本篇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 |
| 静态创建 | xSemaphoreCreateBinaryStatic | xSemaphoreCreateCountingStatic |
| 信号量初始值 | 二进制信号量初始值为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教程详解!!!
前言:本篇教程,参考韦东山,开发文档,连接放在最后 目录 Semaphore基本概念 二值信号量(Binary Semaphore) 计数信号量(Couting Semaphore) 互斥信号量(Mutex&…...
【Postman】接口测试工具使用
干就完啦 Postman发送get请求案例1: Postman发送post请求案例2 Postman发送其他请求Postman测试实战 学习目标:能够使用Postman发送get/post/put/delete请求并获取响应结果 Postman发送get请求 首先postman是一款接口调试工具,支持win&…...
springboot 整合 rabbitMQ(1)
目录 一、MQ概述 二、MQ的优势和劣势 三、常见的MQ产品 RabbitMQ使用步骤 第一步:确保rabbitmq启动并且可以访问15672 第二步:导入依赖 第三步:配置 auto自动确认 manual手工确认(推荐使用!可以防止消息丢失&a…...
Appium Device Farm安装教程
环境要求: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-…...
异常、基类
异常 人生和世界总是充满着意外,争议、冲突和战争似乎是人类必然经历的过程。程序执行也有不满的时候。 不同编程语言的异常 Ada/Modula-3是早期引入异常处理的语言。 C语言没有标准意义的异常,使用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的最新版本对静态分析工具进行了重大改进,通过尽早修复错误、降低开发成本和加快发布速度,使开发团队实现左移。 本文中,我们将概述2024.2版本的新特性和新功能。 CI/CD和左移以实现持续合规性 现代软件开发实…...
太阳能电池特性及其应用
中南民族大学-通信工程2024-大学物理下实验 目录 代码实现结果显示 🛠工具使用 MarsCode(插件,集成在PyCharm); python编程(豆包AI智能体) 💻编程改进 此处是用「Matplotlib」来作图…...
日语学习零基础生活日语口语柯桥外语学校|股票用日语怎么说?
在日语中,“股票”可以说: • 株(かぶ) 这是最常用的表达方式,直接表示“股票”。 例如: 株を買う - 买股票 株を売る - 卖股票 • 株式(かぶしき) 这个词也是“股票”的意…...
第2关:寻找一个序列中的第K小的元素(即第k小元问题)
[TOC]寻找一个序列中的第K小的元素(即第k小元问题) 对于给定的含有n(n<100)元素的无序序列,求这个序列中第k(1≤k≤n)小的元素。 任务描述 本关任务:编写一个能计算数组中的第k小的元素的小程序。 相关…...
docker 搭建 vue3 + vite
vue3发布了,今天就分享一下我使用docker 搭建 vue3 vite 开发环境。至于为什么使用docker搭建,因为多版本可以快速切换,和本地环境避免冲突。好了话不多说我们开始吧。 1. 准备资料 Docker Desktop wsl2 ubuntu 下载地址 : https://www.docker.…...
【网易云音乐】--源代码分享
最近写了一个网易云音乐的音乐实现部分,是通过JavaScript和jQuery实现的,具体效果大家可以参照下面的视频 源代码分享 - git地址: 网易云音乐源代码 下面将着重讲解一下音乐实现部分 视频有点模糊,不好意思,在b站上添加视频的时候…...
股市大涨下的会展业创新者
近期,股市涨势强劲有力,各大指数普遍上扬,市场活力空前。与此同时,伴随全球经济逐步复苏及会展行业不断发展,上市展览公司机遇与挑战并存。国内外市场需求持续增长拓展了广阔发展空间,但同时行业竞争愈发激…...
工具篇-完整的 Git 项目管理工具教程(在命令框中使用 Git、在 IDEA 中使用 Git)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 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实例时,会看到有一个Amazon Linux镜像。 那这个镜像与其他Linux有什么关系和区别呢? 网站是介绍:Amazon Linux 2023 是基于 Linux 的现代化通用操作系统,提供 5 年的长期支持。它针对 AWS 进行了优化࿰…...
Java面向对象编程--高级
目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习,测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…...
Vert.x,Web - 静态资源/模板
静态资源 Vert.x-Web带有开箱即用的处理器(StaticHandler),用于处理静态Web资源(.html, .css, .js, …), 因此可以非常轻松地编写静态Web服务器。 默认静态文件目录为类路径下的webroot目录,对于maven的项目,按规范放在src/main/…...
OpenAI今天Open了一下:开源多智能体框架Swarm
来源 | 机器之心 毫无疑问,多智能体肯定是 OpenAI 未来重要的研究方向之一,前些天 OpenAI 著名研究科学家 Noam Brown还在 X 上为 OpenAI 正在组建的一个新的多智能体研究团队招募机器学习工程师。 就在几个小时前,这个或许还没有组建完成的新…...
车辆重识别(2021NIPS无分类器扩散指南)论文阅读2024/10/08
[1] CLASSIFIER-FREE DIFFUSION GUIDANCE(无分类器扩散指导) (NIPS 2021) 作者:Jonathan Ho & Tim Salimans 单位:Google Research, Brain team(谷歌团队) 摘要: 分类器指导是最近引入的一…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
