[FreeRTOS 内部实现] 信号量
文章目录
- 基础知识
- 创建信号量
- 获取信号量
- 释放信号量
- 信号量 内部实现框图
基础知识
[FreeRTOS 基础知识] 信号量 概念
创建信号量
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U )
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U )
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
根据上面的定义,可知创建信号量本质就是创建队列。长度(第一个参数)为1,大小(第二个参数)为0
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )-> if( uxItemSize == ( UBaseType_t ) 0 ) xQueueSizeInBytes = ( size_t ) 0;-> pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); // 动态分配大小,只有一个Queue_t结构体大小

获取信号量
通过队列获取信号量
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )for( ;; )
{taskENTER_CRITICAL(); // 关中断{const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting; // 获取当前信号量值if( uxSemaphoreCount > ( UBaseType_t ) 0 ) // 信号量值大于0{traceQUEUE_RECEIVE( pxQueue );pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; // 信号量-1// 检查是否有其他任务阻塞等待信号量。if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ){// 如果是,解除阻塞最高优先级的任务。// 1、将最高阻塞任务从xTasksWaitingToSend链表中移除;// 2、将最高阻塞任务从从DelayList移动到ReadyList链表if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ){queueYIELD_IF_USING_PREEMPTION(); // 让出CPU使用权}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}taskEXIT_CRITICAL(); //开中断return pdPASS; // 返回成功}else{if( xTicksToWait == ( TickType_t ) 0 ) // 是否愿意等待{// 不愿意等待taskEXIT_CRITICAL(); // 打开中断traceQUEUE_RECEIVE_FAILED( pxQueue );return errQUEUE_EMPTY; // 返回队列空失败}else if( xEntryTimeSet == pdFALSE ){// 信号量计数为0,阻塞时间被指定,所以配置超时结构准备阻塞。vTaskInternalSetTimeOutState( &xTimeOut );xEntryTimeSet = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}}taskEXIT_CRITICAL();vTaskSuspendAll();prvLockQueue( pxQueue );if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ){if( prvIsQueueEmpty( pxQueue ) != pdFALSE ){traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );// 1、当前的任务加入到队列的xTasksWaitingToReceive链表中;// 2、当前的任务从ReadyList移动到DelayListvTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );prvUnlockQueue( pxQueue );if( xTaskResumeAll() == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}} else{prvUnlockQueue( pxQueue );( void ) xTaskResumeAll();}}else{...}
释放信号量
#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U )
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
-> for( ;; ){taskENTER_CRITICAL(); // 关中断 portDISABLE_INTERRUPTS();{if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) // 判断当前信号量是否超过队列信号量长度{ traceQUEUE_SEND( pxQueue );xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );// 不会写数据,但是会将 uxMessagesWaiting +1if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) // 判断xTasksWaitingToReceive队列里是否有等待的任务{if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) // 1、将要写的任务从xTasksWaitingToReceive移除;2、将要写的任务从DelayList移动到ReadyList{queueYIELD_IF_USING_PREEMPTION(); //让出CPU使用权}else{mtCOVERAGE_TEST_MARKER();}} else if( xYieldRequired != pdFALSE ){queueYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}taskEXIT_CRITICAL(); // 开中断return pdPASS; // 返回成功}else{if( xTicksToWait == ( TickType_t ) 0 ){taskEXIT_CRITICAL();traceQUEUE_SEND_FAILED( pxQueue );return errQUEUE_FULL; // 返回队列已满}else if( xEntryTimeSet == pdFALSE ){vTaskInternalSetTimeOutState( &xTimeOut ); // 阻塞时间被指定,所以配置超时结构。 xEntryTimeSet = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}
}
taskEXIT_CRITICAL(); // 开中断vTaskSuspendAll();
prvLockQueue( pxQueue );if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
{if( prvIsQueueFull( pxQueue ) != pdFALSE ){traceBLOCKING_ON_QUEUE_SEND( pxQueue );// 1、当前的任务加入到队列的xTasksWaitingToSend链表中;// 2、当前的任务从ReadyList移动到DelayList vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );prvUnlockQueue( pxQueue );if( xTaskResumeAll() == pdFALSE ){portYIELD_WITHIN_API();}}else{prvUnlockQueue( pxQueue );( void ) xTaskResumeAll();}
}
else
{prvUnlockQueue( pxQueue );( void ) xTaskResumeAll();traceQUEUE_SEND_FAILED( pxQueue );return errQUEUE_FULL;
}
}
信号量 内部实现框图

相关文章:
[FreeRTOS 内部实现] 信号量
文章目录 基础知识创建信号量获取信号量释放信号量信号量 内部实现框图 基础知识 [FreeRTOS 基础知识] 信号量 概念 创建信号量 #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) #define xSe…...
Vue57-组件的自定义事件_解绑
给谁绑的自定义事件,就找谁去触发;给谁绑的自定义事件,就找谁去解绑; 一、解绑自定义事件 1-1、解绑一个自定义事件 到student.vue组件中去解绑。 1-2、解绑多个自定义事件 使用数组来解绑多个。 1-3、解绑所有的自定义事件 二、…...
Java启动jar设置内存分配详解
在微服务架构越来越盛行的情况下,我们通常一个系统都会拆成很多个小的服务,但是最终部署的时候又因为没有那么多服务器只能把多个服务部署在同一台服务器上,这个时候问题就来了,服务器内存不够,这个时候我们就需要对每…...
Feign Client超时时间设置不生效问题
在使用Feign Client时,可以通过两种方式来设置超时时间: 针对整个Feign Client设置超时时间 可以在Feign Client的配置类中通过修改Request.Options对象来设置超时时间。Request.Options对象有两个属性,connectTimeoutMillis用于设置连接超…...
Haproxy部署Web群集
概论 HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,是免费、快速并且可靠的一种解决方案。HAProxy非常适用于并发大(并发达1w以上)web站点,这些站点通常又需要会话保持或七层处理。HAProxy的运行模式使得它可以…...
C++STL梳理
CSTL标准手册: https://cplusplus.com/reference/stl/ https://cplusplus.com/reference/vector/vector/at/ 1、STL基础 1.1、STL基本组成(6大组件13个头文件) 通常认为,STL 是由容器、算法、迭代器、函数对象、适配器、内存分配器这 6 部分构成&…...
找出1000以内的所有的完数
完数的概念:完数(Perfect Number)是一个正整数,它等于除了它本身以外所有正因子之和。例如,6的因子有1、2、3和6,其中1236,所以6是一个完数。 #include <stdio.h> // 函数用于计算一个数…...
3110. 字符串的分数
给你一个字符串 s 。一个字符串的 分数 定义为相邻字符 ASCII 码差值绝对值的和。 请你返回 s 的 分数 。 示例 1: 输入:s "hello" 输出:13 解释: s 中字符的 ASCII 码分别为:h 104 ,e 1…...
Mybatis MySQL allowMultiQueries 一次性执行多条语句
在JDBC 增加参数allowMultiQueries jdbc:mysql://localhost:3306/abc?&allowMultiQueriestrue <insert id"addRi" parameterType"java.util.List">DELETE FROM sys_ri WHERE sr_id #{roId} AND sr_fion_id #{fod};INSERT into sys_rVALUES&…...
Kubernates容器化JVM调优笔记(内存篇)
Kubernates容器化JVM调优笔记(内存篇) 先说结论背景思路方案 先说结论 1、首先如果是JDK8,需要使用JDK8_191版本以上,才支持容器化环境和以下参数,否则就更新到JDK10以上,选择对应的镜像构建就行了 2、在容…...
Elasticsearch Scroll 报错entity content is too long
2024-06-24 15:22:01:568 ERROR [task-31] (ScrollFetcherProduceAction.java:129) 访问ES出错org.apache.http.ContentTooLongException: entity content is too long [112750110] for the configured buffer limit [104857600]at org.elasticsearch.client.HeapBufferedAsync…...
Vue iview输入框change事件replace正则替换不生效问题的解决。
// 需求:输入座机号只允许输入数字和"-" onChange(e){this.$nextTick(()>{this.phone e.target.value.replace(/[^0-9-]/g, );}) } 解决:添加**this.$nextTick**即可...
Prestashop跨境电商独立站,外贸B2C网站完整教程
Prestashop是一款来自法国专业的开源电商CMS(内容管理系统)平台,和wordpress一样比较轻量,适合中小网站。Prestashop跨境电商独立站在国内并不是很流行,不过国外是非常火的,从各大平台的Prestashop主题数量就可以看得出来。 最有…...
常用算法及参考算法 (1)累加 (2)累乘 (3)素数 (4)最大公约数 (5)最值问题 (6)迭代法
常用算法及参考算法 (1)累加 (2)累乘 (3)素数 (4)最大公约数 (5)最值问题 (6)迭代法 1. 累加 #include <stdio.h>int main() {…...
java简易计算器(多种方法)
parseDouble() 方法属于 java.lang.Double 类。它接收一个字符串参数,其中包含要转换的数字表示。如果字符串表示一个有效的 double,它将返回一个 double 值。 应用场景 parseDouble() 方法在以下场景中非常有用: 从用户输入中获取数字&a…...
spring的bean定义和扫描规则
1、bean的基本定义 在Spring框架中,Bean是一个核心概念,它是Spring IoC(Inverse of Control,控制反转)容器管理的一个对象实例。简单来说,Bean就是由Spring容器初始化、配置和管理的对象。这些对象可以是J…...
软件工程体系概念
软件工程 软件工程是应用计算机科学、数学及 管理科学等原理开发软件的工程。它借鉴 传统工程的原则、方法,以提高质量,降 低成本为目的。 一、软件生命周期 二、软件开发模型 1.传统模型 瀑布模型、V模型、W模型、X 模型、H 模型 (1)瀑布模型 瀑布…...
史上最全整合nacos单机模式整合哈哈哈哈哈
Nacos 是阿里巴巴推出的一个新开源项目,它主要是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos提供了一组简单易用的特性集,帮助用户快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 的关键特性包括&#x…...
Python xml.dom.minidom 读取XML元素
哈喽,大家好,我是木头左! 什么是 XML? XML(可扩展标记语言)是一种用于描述数据结构和交换数据的标记语言。它被广泛用于 Web 应用程序中,用于存储和传输数据。XML 具有自描述性,因此可以很容易地理解和处理。 Python 中的 xml.dom.minidom Python 提供了一个内置的库…...
【Python/Pytorch 】-- K-means聚类算法
文章目录 文章目录 00 写在前面01 基于Python版本的K-means代码02 X-means方法03 最小二乘法简单理解04 贝叶斯信息准则 00 写在前面 时间演变聚类算法:将时间演变聚类算法用在去噪上,基本思想是,具有相似信号演化的体素具有相似的模型参数…...
Python数据库操作优化:从原理到实践
Python数据库操作优化:从原理到实践 1. 背景与动机 数据库操作是Web应用和数据处理系统的核心环节。优化数据库操作可以显著提升应用性能。本文将介绍Python数据库操作的优化技巧和最佳实践。 2. 核心原理 2.1 数据库性能瓶颈 网络延迟:应用与数据库的通…...
保障AI安全:YOLOv12模型鲁棒性测试与对抗样本防御
保障AI安全:YOLOv12模型鲁棒性测试与对抗样本防御 在智能安防、自动驾驶这些关键领域,AI模型,尤其是像YOLOv12这样的目标检测模型,已经成为了核心的“眼睛”。我们依赖它来识别行人、车辆,做出至关重要的判断。但你想…...
AIGlasses_for_navigation网络通信基础:TCP/IP协议栈与实时数据传输优化
AIGlasses_for_navigation网络通信基础:TCP/IP协议栈与实时数据传输优化 最近和几个做智能眼镜导航项目的朋友聊天,他们都在为一个问题头疼:眼镜端看到的导航画面,有时候会卡顿一下,或者指令响应慢半拍。这听起来是小…...
手把手教你用脉动阵列实现FIR滤波器:从理论到VLSI设计的完整流程
手把手教你用脉动阵列实现FIR滤波器:从理论到VLSI设计的完整流程 在数字信号处理领域,FIR滤波器因其线性相位特性和稳定性而广受欢迎。但当面对高性能、低功耗的应用场景时,传统实现方式往往难以满足需求。脉动阵列(Systolic Arr…...
别再手动点点点了!用Python脚本自动化调用Dify工作流API(附完整代码)
用Python脚本实现Dify工作流API的自动化调用与生产级实践 在数据处理和AI应用开发中,手动操作Web界面不仅效率低下,也难以应对批量任务的需求。本文将介绍如何通过Python脚本将Dify工作流API封装为可复用的自动化工具,并分享生产环境中常见的…...
构建学术文献自由:caj2pdf开源转换工具深度解析
构建学术文献自由:caj2pdf开源转换工具深度解析 【免费下载链接】caj2pdf Convert CAJ (China Academic Journals) files to PDF. 转换中国知网 CAJ 格式文献为 PDF。佛系转换,成功与否,皆是玄学。 项目地址: https://gitcode.com/gh_mirro…...
离散裂隙注浆与COMSOL的应用
离散裂隙注浆 comsol裂隙注浆模拟这件事,搞过岩土工程的都懂——看着像往裂缝里灌水泥,实际操作起来比煮一锅意大利面还容易翻车。COMSOL在这块儿的优势就像给工程师开了透视挂,尤其是处理随机分布的离散裂隙时,能直接把三维地质结…...
排序算法---(四)
引言在前几篇文章里面讲到了六种排序,今天来讲一下剩下两种:基数排序、堆排序基数排序1.思路(1)首先确定最大数的位数:找到待排序数组中的最大数,并确定其位数(2)将元素按照相应的位…...
Qwen3-4B-Instruct-2507问题解决:部署中常见的5个错误及快速修复方法
Qwen3-4B-Instruct-2507问题解决:部署中常见的5个错误及快速修复方法 1. 部署准备与环境检查 在开始部署Qwen3-4B-Instruct-2507模型之前,确保您的环境满足以下基本要求: 硬件配置:推荐使用NVIDIA 4090D显卡(24GB显…...
FireRedASR-AED-L语音识别模型WebUI快速部署教程:Python环境一键配置
FireRedASR-AED-L语音识别模型WebUI快速部署教程:Python环境一键配置 语音识别技术正在快速融入我们的日常开发,无论是做智能客服、会议纪要,还是内容审核,一个好用的识别模型都能省下大量时间。但很多朋友在第一步——环境部署上…...
