一、核心定义(一句话说清)
信号量(Semaphore):是一个计数器。它通过一个数值(0到N)来管理资源数量或传递单一事件。操作是“拿走(Take)减1,释放(Give)加1”。
事件组(Event Group):是一个位图(Bit Map)。它用一个整数的每一位代表一个独立的事件(如Bit0=按键,Bit1=数据到达)。操作是“置位(Set)”和“清除(Clear)”。
二、事件组 vs 信号量:最本质的5点区分
| 对比维度 | 信号量 (Semaphore) | 事件组 (Event Group) |
|---|---|---|
| 管理对象 | “数量”(还剩几份资源/几次信号) | “状态”(哪些条件当前成立了) |
| 等待逻辑 | 线性:只要计数值 > 0,就唤醒任务 | 组合逻辑:支持“与(AND)”和“或(OR)”,可同时等待多个事件 |
| 事件消费 | 消耗性:Take 一次,计数值减 1 | 状态保持:位被置 1 后会一直保持,直到任务主动清除 |
| 唤醒方式 | 单播:释放一次通常只唤醒等待队列中优先级最高的一个任务 | 广播:事件满足条件时,可同时唤醒所有等待该组合的任务 |
| 中断适用性 | 极优(有轻量级FromISR版本) | 受限(FromISR版本耗时较长,不适合高频中断) |
事件组:是可以挂起这个事件的所有任务,和唤醒这个事件挂起的所有任务。
三、信号量的完整分类(4种)
信号量根据计数能力和所有权机制,又分为以下4种,它们同属“信号量”家族:
| 分类 | 计数值范围 | 所有权 | 优先级继承 | 核心用途 | FreeRTOS 创建函数 |
|---|---|---|---|---|---|
| 1. 二进制信号量 | 0 ~ 1 | ❌ 无 | ❌ 无 | 任务同步(中断发信号,任务处理) | xSemaphoreCreateBinary() |
| 2. 计数信号量 | 0 ~ N | ❌ 无 | ❌ 无 | 管理多个相同资源(如5个缓冲区)或“生产-消费”计数 | xSemaphoreCreateCounting() |
| 3. 互斥锁(Mutex) | 0 ~ 1 | ✅有(谁拿谁放) | ✅支持 | 保护共享资源(独占访问外设/全局变量) | xSemaphoreCreateMutex() |
| 4. 递归互斥锁 | 0 ~ 1 | ✅有(允许嵌套) | ✅支持 | 函数嵌套保护同一资源(防止自己挂起自己) | xSemaphoreCreateRecursiveMutex() |
特别注意:互斥锁和递归互斥锁虽然有“优先级继承”,但严禁在中断ISR中使用(因为涉及任务挂起和优先级变更)。