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

FreeRTOS四种信号量详解

FreeRTOS四种信号量详解

前言

上期我们详细介绍了队列的常用操作,本期让我们深入探讨FreeRTOS中的信号量机制。信号量顾名思义是用于传递信号的量,与队列类似,也是实现任务间通信的重要机制,能够有效实现任务同步或临界资源的互斥访问。

同步与互斥概念

在详细介绍信号量前,我们需要先明确同步与互斥的基本概念。

同步

同步类似于生产者与消费者的关系:消费者必须等待生产者生产出数据后才能进行操作。在FreeRTOS中,数据采集和处理通常分为多个程序块,需要我们协调它们的执行顺序。这种协调就是同步,目的是确保多个程序块严格按照预定顺序执行,保证程序逻辑正确。

互斥

互斥则是防止同一资源被多个任务同时访问的机制。例如,任务A正在使用串口发送数据,此时如果高优先级的任务B也要使用同一串口,若没有互斥保护,任务B会中断任务A的发送操作,导致数据错乱。互斥机制确保资源在同一时刻只能被一个任务访问。

FreeRTOS信号量类型

FreeRTOS提供了四种类型的信号量,每种都有其特定用途:

  1. 计数信号量(Counting Semaphore)
  2. 二值信号量(Binary Semaphore)
  3. 互斥信号量(Mutex)
  4. 递归互斥信号量(Recursive Mutex)

计数信号量与二值信号量

信号量本质上是一种特殊的队列,区别在于:队列可以传递具体数据,而信号量只传递信号。既然信号量也是队列,为何还需要单独设计呢?

原因是:有时我们只需传递状态信息,无需传递具体数据。比如上面串口的例子,两个任务之间的数据没有直接联系,只有串口状态需要共享,因此只要传递状态信号即可。用队列传递状态也可以,但会浪费更多内存空间,所以产生了更轻量的信号量。

计数信号量与二值信号量的区别

  • 计数信号量的计数值没有上限限制
  • 二值信号量的计数值仅能为0或1

互斥信号量与递归互斥信号量

这两种信号量主要用于实现互斥访问。那么,既然二值信号量已经可以实现互斥,为什么还需要互斥信号量呢?

这涉及到一个关键问题:优先级反转

优先级反转问题

假设有三个不同优先级的任务(优先级:任务3 > 任务2 > 任务1),且任务1和任务3都需要使用串口:

  1. 任务1正在使用串口(已获取信号量)
  2. 此时任务2抢占了任务1的CPU时间(因优先级更高)
  3. 随后任务3也抢占了任务2(因优先级最高)
  4. 但任务3需要串口资源,而串口被任务1占用
  5. 任务3无法获取串口,只能将CPU控制权还给任务2
  6. 任务3必须等待任务2执行完毕,任务1释放串口后才能执行

结果:优先级最高的任务3最后才得以执行——这就是优先级反转

互斥信号量解决方案:优先级继承

互斥信号量通过优先级继承机制解决优先级反转问题:

当任务3发现无法获取被任务1占用的资源时,系统会临时提升任务1的优先级(继承任务3的优先级),使任务1能够立即执行并尽快释放资源。任务1释放资源后,任务3继续执行,任务1恢复原优先级。

需要注意:

  • 优先级继承只能缩短优先级反转的时间,无法完全避免
  • 互斥信号量本质是带有优先级继承机制的二值信号量
  • 互斥信号量不能在中断中使用
递归互斥信号量

递归互斥信号量解决了互斥信号量的两个主要缺陷:

  1. 误释放问题:互斥信号量可以被任何任务释放,而不仅限于获取该信号量的任务。如果任务A正在使用资源,任务C错误地释放并获取了信号量,会导致资源冲突。

  2. 死锁问题:同一任务多次获取互斥量会导致死锁。例如,任务首次获取互斥量成功,第二次获取由于未释放而陷入休眠,导致无法释放互斥量而永久阻塞。

递归互斥信号量的特点:

  • 只能由获取者释放(谁获取谁释放)
  • 同一任务可以多次获取,但需要相同次数的释放
  • 具有与互斥信号量相同的优先级继承机制

信号量API简介

这里简单列出FreeRTOS信号量的核心API函数,下期将详细介绍其使用方法:

// 二值信号量
xSemaphoreCreateBinary();           // 创建二值信号量
xSemaphoreTake(xSemaphore, xTime);  // 获取信号量
xSemaphoreGive(xSemaphore);         // 释放信号量// 计数信号量
xSemaphoreCreateCounting(uxMaxCount, uxInitialCount); // 创建计数信号量// 互斥信号量
xSemaphoreCreateMutex();            // 创建互斥信号量// 递归互斥信号量
xSemaphoreCreateRecursiveMutex();   // 创建递归互斥信号量
xSemaphoreTakeRecursive(xMutex, xBlockTime); // 获取递归互斥信号量
xSemaphoreGiveRecursive(xMutex);    // 释放递归互斥信号量

信号量选择指南

在实际开发中,如何选择合适的信号量类型?

  1. 需要事件计数:使用计数信号量
  2. 仅需同步,无资源竞争:使用二值信号量
  3. 需要互斥访问资源,可能有优先级反转:使用互斥信号量
  4. 需要互斥且同一任务可能多次获取:使用递归互斥信号量

结语

本期文章简要介绍了FreeRTOS中的四种信号量类型,以及同步与互斥的基本概念。下期将详细讲解各种信号量的API函数使用方法和实际案例。

🔥 更多精彩内容:我在GitHub上维护了一个完整的FreeRTOS学习资源库,包含从入门到精通的详细教程、示例代码和项目实战。欢迎star和fork!

参考资料

  1. FreeRTOS官方文档:FreeRTOS.org
  2. FreeRTOS学习资源库

如果您觉得这篇文章有帮助,请点赞、收藏、关注!下期将详细介绍信号量API的使用方法和实战案例,敬请期待!

相关文章:

  • Docker私有仓库页面访问实现
  • Python----机器学习(基于PyTorch框架的逻辑回归)
  • 代码随想录算法训练营第十九天
  • 【Python进阶】字符串操作全解与高效应用
  • LTSPICE仿真电路:(二十七)三极管伏安特性曲线仿真
  • 未启用CUDA支持的PyTorch环境** 中使用GPU加速解决方案
  • 时序数据预测:TDengine 与机器学习框架的结合(一)
  • 微信小程序数字滚动效果
  • JVM:堆、方法区
  • chili3d调试笔记2
  • 文章记单词 | 第34篇(六级)
  • 时序数据预测:TDengine 与机器学习框架的结合(二)
  • 图神经网络入门代码(2)-逐行分析
  • Windows 图形显示驱动开发-WDDM 1.2功能—Windows 8 中的 DirectX 功能改进(二)
  • 7系列fpga在线升级和跳转
  • LINUX 416 路由转发1
  • 计算机视觉与深度学习 | 图像特征点提取算法及匹配算法综述
  • 使用 tcpdump 工具,捕获并分析
  • 照片处理工具:基于HTML与JavaScript实现详解
  • 实验三 I/O地址译码
  • 网站使用协议书/网上销售平台
  • 有横向滚动条的网站/西安seo招聘
  • 品牌网站建设策划/最新天气预报最新消息
  • 网站建设软件开发工作室整站模板/百度网盘人工客服电话
  • microsoft做网站/线上广告
  • 网站栏目规划/网站推广哪个好