FreeRTOS学习笔记(应用)-- 各种 信号量的应用场景

文章目录

在单片机上使用FreeRTOS时,信号量是任务间同步、互斥或资源管理的核心机制。FreeRTOS中常用的信号量类型包括 二进制信号量计数信号量互斥信号量(Mutex)递归互斥信号量 ,它们的应用场景有明确区分,具体如下:

1. 二进制信号量(Binary Semaphore)

二进制信号量只有两种状态:可用(1)不可用(0) ,核心用途是同步(任务间或中断与任务间的"事件通知")。

典型应用场景:
  • 中断与任务同步

    单片机的外部中断(如按键、传感器触发)通常需要快速响应,复杂逻辑(如按键防抖、数据解析)适合放在任务中处理。此时,中断服务程序(ISR)可通过释放二进制信号量"通知"任务,任务则阻塞等待信号量,实现"中断触发→任务处理"的同步。

    例:按键按下触发外部中断,ISR中调用xSemaphoreGiveFromISR()释放信号量,按键处理任务通过xSemaphoreTake()等待信号量,获取后执行按键逻辑(避免在ISR中做耗时操作)。

  • 任务间同步

    一个任务完成某操作后,通知另一个任务开始执行。例如:传感器采集任务(A)完成数据采集后,释放信号量,数据处理任务(B)等待信号量后开始处理数据,实现"A完成→B启动"的顺序控制。

2. 计数信号量(Counting Semaphore)

计数信号量的状态是一个非负整数(计数),可用于资源数量管理事件次数统计 ,计数的范围由创建时的uxMaxCount限制。

典型应用场景:
  • 有限资源管理

    当多个任务需要竞争访问有限数量的共享资源时(如缓冲区、外设通道),计数信号量的初始值设为资源总数,任务获取资源时计数减1,释放时计数加1。

    例:单片机有3个UART发送缓冲区,计数信号量初始化为3。任务需要发送数据时,先通过xSemaphoreTake()获取信号量(占用1个缓冲区),发送完成后通过xSemaphoreGive()释放(归还缓冲区),确保缓冲区不被超额占用。

  • 事件计数

    统计某事件发生的次数,任务可一次性处理多次事件。例如:高频传感器(如加速度计)每采集一次数据就释放一次信号量(计数+1),数据处理任务可通过xSemaphoreTake()一次获取多个计数(如一次处理10次采集的数据),减少任务唤醒频率。

3. 互斥信号量(Mutex)

互斥信号量本质是一种特殊的二进制信号量,用于保护共享资源 (防止多个任务同时访问导致数据混乱),核心特性是优先级继承(避免优先级反转)。

典型应用场景:
  • 共享外设/资源的互斥访问
    单片机中多个任务可能需要访问同一外设(如I2C总线、SPI设备、全局变量),此时需用Mutex确保"同一时间只有一个任务访问资源"。
    例:任务A(低优先级)和任务B(高优先级)都需要通过I2C访问温湿度传感器。任务A获取Mutex后正在操作I2C时,任务B就绪:若用普通二进制信号量,任务B会一直等待(优先级反转),而Mutex的优先级继承机制会临时提升任务A的优先级,让其快速释放资源,避免高优先级任务长期阻塞。

4. 递归互斥信号量(Recursive Mutex)

递归互斥信号量允许同一任务多次获取信号量(需对应多次释放),用于任务中存在"嵌套访问共享资源"的场景,避免自我死锁。

典型应用场景:
  • 嵌套函数访问共享资源
    当一个任务中的函数A调用函数B,且A和B都需要访问同一共享资源时,普通Mutex会导致死锁(任务已持有Mutex,再次获取时会阻塞自己)。递归Mutex允许同一任务多次获取,只需释放次数与获取次数相同即可。
    例:单片机的日志模块中,log_debug()函数调用log_write()函数,两者都需要访问日志缓冲区(共享资源)。用递归Mutex保护缓冲区,log_debug()获取后,log_write()可再次获取,避免死锁。

总结

  • 二进制信号量:侧重"同步"(事件通知),如中断-任务、任务-任务的触发。
  • 计数信号量:侧重"数量管理",如有限资源分配或事件次数统计。
  • 互斥信号量:侧重"共享资源保护",解决多任务竞争,带优先级继承。
  • 递归互斥信号量:侧重"嵌套访问保护",避免同一任务的自我死锁。

实际使用时需根据场景选择,避免滥用(如用Mutex做同步会浪费优先级继承的开销,用二进制信号量做互斥可能导致优先级反转)。

相关推荐
星星火柴9362 小时前
笔记 | C++面向对象高级开发
开发语言·c++·笔记·学习
BeingACoder2 小时前
【SAA】SpringAI Alibaba学习笔记(一):SSE与WS的区别以及如何注入多个AI模型
java·笔记·学习·saa·springai
安全不再安全3 小时前
免杀技巧 - 早鸟注入详细学习笔记
linux·windows·笔记·学习·测试工具·web安全·网络安全
BreezeJuvenile3 小时前
外设模块学习(8)——HC-SR04超声波模块(STM32)
stm32·单片机·嵌入式硬件·学习·超声波测距模块·hc-sr04
LBuffer4 小时前
破解入门学习笔记题三十八
笔记·学习
微露清风4 小时前
系统性学习C++-第十讲-stack 和 quene
java·c++·学习
PyAIGCMaster4 小时前
钉钉的设计理念方面,我可以学习
人工智能·深度学习·学习·钉钉
Elias不吃糖5 小时前
第四天学习总结:C++ 文件系统 × Linux 自动化 × Makefile 工程化
linux·c++·学习
CodeCraft Studio5 小时前
PPT处理控件Aspose.Slides教程:使用Java将PowerPoint笔记导出为PDF
java·笔记·pdf·powerpoint·aspose·ppt转pdf·java将ppt导出pdf