返回 IPC 通信机制 HRTOS / SYSTEM MODULES / IPC
HRTOS · INTER-PROCESS COMMUNICATION

信号量 Semaphore / Counting Synchronization

基于计数状态的任务同步机制。通过等待与释放操作协调任务执行, 可用于资源计数、任务触发以及中断与任务之间的通知。 HRTOS 的相关实现围绕资源状态和等待任务管理展开。

计数同步 任务等待 优先级唤醒 无互斥所有权语义
IPC / SEMAPHORE
OVERVIEW / 01

用计数状态协调任务

信号量的核心是一个可用计数。任务等待信号量时,若计数允许获取, 可消耗一个计数继续运行;若当前没有可用计数,则可能进入等待状态。

与互斥量不同,信号量通常不以某个任务持有资源的所有权作为核心语义。 它更适合表示可用资源数量或通知次数。

VAL
资源计数 OS_RESOURCE.value
WAIT
等待任务管理 wait_mask 等待位图
IPC
任务同步 等待、释放与后续调度
01

核心接口

API Reference · 初始化、等待与释放

信号量通过初始化、等待和释放三个主要操作完成协作。 以下接口按本页提供的 HRTOS 声明整理,参数类型和返回值语义应以当前版本头文件为准。

Semaphore API C / HRTOS
char os_sem_init(u8 sid, char init_val);
char os_sem_post(char sid);
u8 os_sem_wait(u8 sid);
  • os_sem_init():初始化指定信号量的计数状态。
  • os_sem_wait():请求获取一个信号量计数;当前无法获取时的行为由实现决定。
  • os_sem_post():释放信号量或通知等待任务,具体处理顺序以实现为准。
接口类型需要留意
本页提供的 os_sem_wait() 返回类型为 u8, 而初始化与释放接口返回 char。使用时应核对各接口的返回值定义、 错误表示和边界条件,不能直接假定三者采用相同的成功或失败约定。
02

数据模型与资源状态

OS_RESOURCE · 计数与等待关系

按本页所描述的 HRTOS 实现,信号量使用通用资源管理结构中的计数与等待状态, 而不是必须为信号量单独创建一套独立对象布局。

相关字段概念 RESOURCE MODEL
OS_RESOURCE
{
    value       // 资源计数或可用状态
    owner       // 通用资源结构中的所有者相关字段
    wait_mask   // 等待任务位图
    wait_cnt    // 等待计数或预留字段,依实现而定
}
  • value:表示信号量计数状态,是计数型同步的关键字段。
  • wait_mask:记录等待该资源的任务集合,具体位定义由内核实现决定。
  • owner:通用资源结构中可能存在的所有者相关字段;信号量不应因此被理解为互斥量。
  • wait_cnt:其实际用途应根据当前结构体定义和使用位置确认。
字段说明
以上是对原页面所述资源模型的整理,不是完整的源码结构体声明。 正式文档应与当前版本中的字段类型、注释和实际读写位置核对,避免将推断内容当作源代码事实。
03

等待流程

Wait · os_sem_wait()

等待操作首先检查信号量当前是否可获取。 当计数大于零时,常见实现会直接消耗一个计数;计数不可用时, 则可能登记当前任务并进入等待状态。

STEP 01 检查计数

判断当前信号量是否有可获取的计数。

STEP 02 获取或等待

有计数则按实现获取;否则处理等待请求。

STEP 03 恢复执行

条件满足并经调度后,任务继续执行。

等待路径 · 概念示意 WAIT PATH
os_sem_wait()
    │
    ▼
检查 value
    ├─ value > 0
    │      └─ 消耗计数并返回
    │
    └─ value 不可获取
           └─ 按内核机制登记等待并处理任务阻塞

原实现说明提到 WAIT_SEM 与 wait_mask。 具体的任务状态切换顺序、等待登记细节和返回路径, 应以当前版本源码为准。

快路径与执行开销
如果计数可直接获取,等待操作可能无需进入任务阻塞与重新调度流程。 这通常能减少额外调度开销,但实际耗时仍取决于编译结果、内核实现和调用上下文。
04

释放与唤醒流程

Post · os_sem_post()

释放信号量时,需要处理当前等待任务和计数状态之间的关系。 原页面描述的实现策略是:优先检查是否存在等待任务;有等待任务时尝试唤醒, 否则在计数范围允许时增加计数。

STEP 01 检查等待状态

判断是否存在等待该信号量的任务。

STEP 02 唤醒或累加

按实现唤醒等待任务,或增加计数。

STEP 03 后续调度

任务何时运行取决于内核调度规则。

释放路径 · 概念示意 POST PATH
os_sem_post()
    │
    ▼
检查 wait_mask
    ├─ 存在等待任务
    │      └─ 按实现选择并唤醒等待任务
    │
    └─ 没有等待任务
           └─ 检查计数边界并按规则增加 value

原页面指出,等待任务按优先级选择,且计数存在上限。 这两点属于具体实现策略:应进一步核对当前版本的任务选择代码、 计数类型以及溢出处理,不能只根据伪代码推断所有边界行为。

唤醒不等于立即运行
任务被唤醒通常意味着它重新具备参与调度的条件, 并不自动保证该任务在 os_sem_post() 返回前执行。 是否发生立即切换,应根据 HRTOS 的调度规则与调用上下文判断。
05

核心行为语义

Behavior · 计数、等待与释放

Wait / 获取

请求一个可用计数。计数可获取时按实现消耗计数; 否则可能登记等待并暂停当前任务的继续执行。

Post / 释放

通知或释放一个信号量单位。实现可能优先处理等待任务, 也可能在没有等待者时更新计数。

Wait:获取可用计数,或等待条件满足 Post:处理等待任务,或更新计数状态

这里描述的是信号量常见的同步模型,并结合了原页面提供的 HRTOS 行为说明。 具体执行顺序、返回时机和错误情况仍应以当前版本实现为准。

06

关键特性与使用边界

Engineering Notes · 设计时需要考虑的问题
  • 计数同步:适用于资源数量管理或记录待处理通知的场景。
  • 无互斥所有权语义:信号量与互斥量的设计目的不同,不应将其自动视为共享资源的所有权锁。
  • 等待任务管理:当前页面描述的实现使用 wait_mask 记录等待关系,具体位图规则以源码为准。
  • 优先级相关行为:若实现按优先级选择等待任务,应在文档中明确选择规则和调度边界。
  • 计数边界:计数类型及上限决定最大可累积数量,应用应避免无限制地重复释放。
ISR 调用约束
原页面指出信号量可在 ISR 中执行 post,而不能在 ISR 中执行会阻塞的 wait。 在将此规则作为正式 API 保证之前,应确认当前版本对中断上下文的具体限制, 包括允许调用的接口、是否可能触发任务切换以及相关临界区处理。
07

典型应用场景

Application Patterns · 同步而非传递复杂数据

生产者与消费者

生产者完成数据准备后释放信号量,消费者等待通知后处理数据。

中断通知任务

在实现允许的前提下,由中断路径发出通知,让任务在后续调度中处理工作。

资源池管理

用计数表示可用资源数量,例如固定数量的缓冲区或资源单元。

任务同步触发

通过等待与释放建立任务之间的同步关系,减少主动轮询。

信号量不负责保存业务数据
信号量主要表达计数或同步状态。如果任务需要按顺序传递多个数据单元, 应考虑消息队列;如果需要传递具体消息值,则应评估邮箱等适合的数据通信机制。
08

信号量与其他 IPC 机制

IPC Selection · 依据语义选择工具
  • Semaphore:重点是计数、同步和资源数量管理。
  • Mutex:重点是共享资源的互斥访问及相应的所有权规则。
  • Event:重点是表达事件或条件状态,适合任务按状态进行协作。
  • Message Queue:重点是按队列规则缓存并传递有序数据。
  • Mailbox:重点是实现所定义的邮箱消息传递语义。
快速选型 DESIGN GUIDE
需要表示可用数量或同步次数  → Semaphore
需要保护共享资源            → Mutex
需要表达事件或条件状态      → Event
需要缓存并顺序传递数据      → Message Queue
需要邮箱式消息传递          → Mailbox

以上是按常见设计语义进行的选型参考。实际工程中仍应检查 HRTOS 对应接口的真实能力、 调用约束和资源开销,再决定采用哪种机制。