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

freeRTOS学习笔记(十二)--信号量

文章目录

  • 一、同步和互斥
    • 1.1 同步
      • 同步的核心场景与目标
      • FreeRTOS中常用的同步机制
        • 1. 二进制信号量(Binary Semaphore)
        • 2. 计数信号量(Counting Semaphore)
        • 3. 事件标志组(Event Groups)
        • 4. 任务通知(Task Notifications)
        • 5. 消息队列(Message Queues)
      • 同步与互斥的区别
      • 总结
    • 1.2 互斥
      • 互斥的核心问题:资源竞争与数据不一致
      • FreeRTOS中互斥的实现:互斥锁(Mutex)
      • 互斥与同步的核心区别
      • 互斥的使用原则
      • 总结

一、同步和互斥

1.1 同步

在FreeRTOS中,同步(Synchronization) 指的是多个任务之间(或任务与中断之间)为了协调执行节奏、共享事件或传递状态而进行的时序协作机制。其核心目的是确保任务按照预期的逻辑顺序执行,避免因执行时机错乱导致的数据错误、资源冲突或功能失效。

同步的核心场景与目标

在实时操作系统(RTOS)中,多任务并发执行时,往往需要通过同步解决以下问题:

  1. “等待事件”:一个任务需要等待另一个任务(或中断)完成某个操作后才能继续执行(例如,传感器采集任务完成后,数据处理任务才能启动)。
  2. “步调一致”:多个任务需按照特定顺序协同工作(例如,A任务生成数据→B任务处理数据→C任务存储数据,需严格按A→B→C的顺序执行)。
  3. “资源有序访问”:当多个任务共享有限资源(如缓冲区、外设)时,通过同步确保资源使用的时序合理性(区别于“互斥”,同步更侧重“顺序”而非“独占”)。

FreeRTOS中常用的同步机制

FreeRTOS提供了多种同步工具,每种工具适用于不同场景:

1. 二进制信号量(Binary Semaphore)
  • 原理:类似“开关”,只有两种状态(0或1),通常用于单次事件同步

  • 场景

    • 中断服务程序(ISR)通知任务处理事件(例如,串口接收数据后,ISR释放信号量,任务获取信号量后处理数据)。
    • 任务A完成初始化后,释放信号量允许任务B启动。
    // 示例:ISR中释放信号量,任务中等待信号量
    void UART_ISR(void) {xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken); // ISR释放
    }void vDataProcessTask(void *pvParam) {while(1) {xSemaphoreTake(xBinarySemaphore, portMAX_DELAY); // 等待信号量// 处理数据}
    }
    
2. 计数信号量(Counting Semaphore)
  • 原理:信号量值可在0到最大值之间变化,用于统计可用资源数量或事件次数
  • 场景
    • 管理资源池(如5个缓存区,任务获取信号量使用缓存,释放后信号量值加1)。
    • 累计事件次数(如计数按键按下次数,任务批量处理)。
3. 事件标志组(Event Groups)
  • 原理:通过一个32位整数的不同位表示不同事件,任务可等待“任意一个事件”或“所有事件”发生。

  • 场景

    • 任务等待多个事件中的一个(如“传感器A触发”或“传感器B触发”)。
    • 任务等待多个事件同时发生(如“温度达标”且“湿度达标”后启动风扇)。
    // 示例:等待两个事件同时发生
    EventBits_t xBits = xEventGroupWaitBits(xEventGroup,          // 事件组(1 << 0) | (1 << 1),  // 等待事件0和事件1pdTRUE,               // 获取后清除标志位pdTRUE,               // 需两个事件同时发生portMAX_DELAY         // 无限等待
    );
    if( (xBits & ((1 << 0) | (1 << 1))) == ((1 << 0) | (1 << 1)) ) {// 两个事件均发生,执行操作
    }
    
4. 任务通知(Task Notifications)
  • 原理:通过直接向任务发送通知(替代信号量/事件组),效率更高(无需创建额外内核对象)。
  • 场景:轻量级同步(如替代二进制信号量,减少内存开销)。
5. 消息队列(Message Queues)
  • 原理:通过队列传递数据,同时隐含同步功能(发送方和接收方需等待队列有空间/有数据)。
  • 场景:同步+数据传递(如任务A发送数据到队列,任务B等待队列有数据后处理)。

同步与互斥的区别

需注意,同步与“互斥(Mutex)”是不同概念:

  • 同步:解决“时序协调”问题,确保任务按逻辑顺序执行(如“先生产后消费”)。
  • 互斥:解决“资源独占”问题,防止多个任务同时访问共享资源(如用互斥锁保护全局变量)。

例如:两个任务共享打印机时,互斥确保同一时间只有一个任务使用打印机;而同步可能确保“任务A打印完文档1后,任务B才能打印文档2”。

总结

FreeRTOS中的同步是多任务协作的核心机制,通过信号量、事件标志组等工具,确保任务(或中断)按照预期的时序执行,避免因并发导致的逻辑混乱。实际开发中,需根据具体场景(如事件数量、是否传递数据、资源类型)选择合适的同步工具,以保证系统的实时性和可靠性。

1.2 互斥

在FreeRTOS(或更广泛的操作系统领域)中,互斥(Mutual Exclusion,简称“互斥”) 是一种解决多个任务对共享资源竞争访问的机制,核心目标是确保同一时间只有一个任务能访问特定的共享资源,从而避免因并发操作导致的数据错乱、逻辑冲突或系统异常。

互斥的核心问题:资源竞争与数据不一致

在多任务系统中,多个任务可能同时需要访问“共享资源”(如全局变量、硬件外设、缓冲区等)。如果缺乏协调,可能出现以下问题:

  • 例如,任务A和任务B同时向同一个串口发送数据,最终输出的内容会变成两者的混合乱码;
  • 任务A读取全局变量count=5并执行count++(计划改为6),但执行中途被任务B抢占,任务B读取count=5并改为6,随后任务A恢复执行,继续将count改为6——最终结果应为7,却错误地变成6。

这种因“同时访问”导致的错误,称为资源竞争(Race Condition)。互斥机制的作用就是通过“独占访问”避免此类问题。

FreeRTOS中互斥的实现:互斥锁(Mutex)

FreeRTOS通过互斥锁(Mutex) 实现互斥功能,其本质是一种特殊的信号量,具有以下特性:

  1. 独占性
    互斥锁只有“持有”和“释放”两种状态。当一个任务获取(take)互斥锁后,其他任务必须等待(block),直到该任务释放(give)互斥锁,才能有机会获取。

    // 示例:创建互斥锁并使用
    SemaphoreHandle_t xMutex;void vInitTask(void *pvParam) {xMutex = xSemaphoreCreateMutex(); // 创建互斥锁// ... 创建其他任务
    }void vTaskA(void *pvParam) {while(1) {// 尝试获取互斥锁,最多等待100msif(xSemaphoreTake(xMutex, 100) == pdTRUE) {// 成功获取锁,安全访问共享资源(如全局变量、串口)shared_data = 123;printf("TaskA: %d\n", shared_data);xSemaphoreGive(xMutex); // 释放锁}vTaskDelay(100);}
    }void vTaskB(void *pvParam) {while(1) {// 尝试获取互斥锁,无限等待if(xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {// 安全访问共享资源shared_data = 456;printf("TaskB: %d\n", shared_data);xSemaphoreGive(xMutex); // 释放锁}vTaskDelay(150);}
    }
    
  2. 优先级继承(Priority Inheritance)
    这是FreeRTOS互斥锁的关键特性,用于解决“优先级反转”问题:

    • 优先级反转:低优先级任务持有互斥锁时,中等优先级任务抢占CPU,导致高优先级任务(等待该锁)被长时间阻塞,违背实时性要求。
    • 优先级继承:当高优先级任务等待低优先级任务持有的互斥锁时,低优先级任务的优先级会临时提升到与高优先级任务相同,直到释放锁,从而避免被中等优先级任务抢占,保证高优先级任务的响应速度。
  3. 所有权
    互斥锁具有“所有权”概念——只有获取锁的任务才能释放锁(信号量则无此限制)。这避免了其他任务误释放锁导致的混乱。

互斥与同步的核心区别

维度互斥(Mutex)同步(如信号量、事件组)
核心目标解决“资源独占”问题,防止竞争访问解决“时序协调”问题,确保任务按逻辑顺序执行
关注点资源的“安全性”(数据一致、操作正确)任务的“有序性”(先做什么,后做什么)
典型场景多个任务访问同一串口、全局变量、硬件外设等任务A等待任务B完成初始化、中断通知任务处理数据等
关键特性优先级继承、所有权信号量计数、事件标志位组合等

互斥的使用原则

  1. 最小持有时间:获取互斥锁后,应尽快完成对共享资源的操作并释放锁,减少其他任务的等待时间。
  2. 避免嵌套死锁:不要在持有一个互斥锁时尝试获取另一个互斥锁(或同一锁),否则可能导致任务相互等待(死锁)。
  3. 适配场景:仅对“需要独占访问的共享资源”使用互斥锁,无需保护的资源(如只读变量)无需加锁,避免过度消耗系统资源。

总结

互斥是FreeRTOS中保障共享资源安全访问的核心机制,通过互斥锁实现“同一时间仅一个任务访问资源”,并通过优先级继承解决实时性问题。它与同步机制(如信号量)相辅相成:同步确保任务“按顺序执行”,互斥确保资源“被安全访问”,共同支撑多任务系统的稳定运行。

http://www.dtcms.com/a/545129.html

相关文章:

  • BLIP 系列全解析与深度面经:从视觉语言统一到跨模态对齐的演进
  • TCP 和 UDP 的核心区别:从原理到场景的全面解析
  • 做外贸网站基本流程wordpress d8 4.1
  • Backend - HTTP请求的常用返回类型(asp .net core MVC)
  • 国内最大的网站制作公司免费创建属于自己的网站
  • [人工智能-大模型-103]:模型层 - M个神经元组成的单层神经网络的本质
  • 【面试题】缓存先删后写如何避免窗口期的旧数据写入缓存
  • 扩展名网站最新新闻事件摘抄
  • 网站免费推广方法网站正能量免费推广软件
  • Spring Boot3零基础教程,配置 GraalVM 环境,笔记88
  • TCN-Transformer-LSTM多特征分类预测Matlab实现
  • 进程 线程 协程基本概念和区别 还有内在联系
  • Linux(1)rsyslog(1)基础使用
  • Arbess零基础学习,安装与配置
  • 温州网站建设seo跨境电商平台shopee
  • Rust——Tokio的多线程调度器架构:深入异步运行时的核心机制
  • webpack - 常用的 CSS 加载器(webpack与其常见loader加载器使用方式)
  • PyTorch2 Python深度学习 - 张量(Tensor)的定义与操作
  • 微信小程序开发案例 | 通讯录小程序(上)
  • 做网站要学什么专业大连谷歌seo
  • 深圳做网站公司营口化工网站建设
  • CUDA-GDB(13)——支持的平台及常见问题解决
  • Warp是什么
  • Go语言设计模式:建造者模式详解
  • 外观模式:复杂系统的统一入口
  • 个人做网站模版是否有人买如何引用网站图片
  • 库卡机器人通讯-EtherKRL-XML格式
  • 自动驾驶技术全景解析:从感知、决策到控制的演进与挑战
  • 建站平台在线提交表格apache 配置网站
  • 前端HTTP,JavaScript,网络