资源计数
信号量维护一个计数器,表示可用资源的数量。 初始化时设置初始值,wait 操作减少计数,post 操作增加计数。
信号量用于任务同步与资源管理,通过计数机制控制并发访问, 实现阻塞、唤醒与调度协作。信号量是 RTOS 并发控制的基础机制之一。
系统运行生产者任务与消费者任务,通过信号量实现任务间同步。 生产者释放资源,消费者等待并获取资源,验证信号量的阻塞与唤醒机制。
信号量是 RTOS 任务同步的核心机制
信号量(Semaphore)是一种用于任务同步和资源管理的同步原语。 通过计数机制控制对共享资源的并发访问,当资源不足时任务会阻塞等待, 当资源释放时会唤醒等待的任务,实现任务间的协作与调度联动。
信号量维护一个计数器,表示可用资源的数量。 初始化时设置初始值,wait 操作减少计数,post 操作增加计数。
当计数为 0 时,申请资源的任务会被放入阻塞队列等待。 阻塞队列维护所有等待该信号量的任务状态。
当资源释放(post)时,信号量会从阻塞队列中选择一个任务唤醒。 被唤醒的任务重新进入就绪队列,等待调度器执行。
信号量的阻塞和唤醒操作会触发任务调度。 任务阻塞时调度器选择其他就绪任务执行,唤醒时可能触发优先级调度。
HRTOS 如何实现信号量同步
在 HRTOS 中,信号量的实现围绕资源计数、阻塞队列、唤醒机制和调度联动四个核心环节展开。 每个环节都经过精心设计,确保同步机制的高效性和可靠性。
检查计数:计数 > 0 则获取成功,计数减 1
阻塞等待:计数 = 0 时任务进入阻塞队列
状态转换:任务从 Running 状态进入 Blocked 状态
调度触发:阻塞时触发调度器选择其他任务
队列管理:任务加入信号量的等待队列
状态保存:保存任务上下文到任务栈
超时支持:支持带超时的等待操作
优先级维护:阻塞队列按优先级排序
计数增加:信号量计数加 1
唤醒检查:检查是否有等待任务
任务唤醒:从等待队列中选择任务唤醒
调度触发:唤醒时可能触发任务调度
状态转换:任务从 Blocked 状态进入 Ready 状态
就绪队列:任务加入就绪队列等待调度
优先级调度:根据任务优先级决定执行顺序
上下文恢复:调度器选择时恢复任务执行
信号量从初始化到任务同步的完整执行路径
信号量同步的完整实现
task_A 生产者任务和 task_B 消费者任务,通过信号量实现同步
#include "hrtos.h"
#define SEM_ID 0
sbit LED_PRODUCER = P1^0;
sbit LED_CONSUMER = P1^1;
sbit LED_SEM = P1^2; // semaphore state indicator
/* 生产者任务 */
void task_A(void)
{
while(1)
{
os_delay(2);
os_sem_post(SEM_ID);
LED_PRODUCER = ~LED_PRODUCER; // 生产节奏闪烁
LED_SEM = 1; // 表示资源"被释放/可用"
}
}
/* 消费者任务 */
void task_B(void)
{
while(1)
{
/* 等待资源 */
if(os_sem_wait(SEM_ID))
{
/* 获取资源成功 */
LED_CONSUMER = ~LED_CONSUMER; // 消费节奏
LED_SEM = 0; // 表示资源被消耗
/* 模拟处理 */
os_delay(1);
}
os_delay(1);
}
}
hrtos_main 函数,初始化信号量并创建生产者和消费者任务
/* 系统入口 */
void hrtos_main(void)
{
LED_PRODUCER = 0;
LED_CONSUMER = 0;
LED_SEM = 0;
os_sem_init(SEM_ID, 0);
os_task_create((unsigned int)task_A, 1, 3, 5);
os_task_create((unsigned int)task_B, 2, 2, 5);
}
示例执行后的预期行为
使用本示例时需要关注的关键点
信号量用于任务同步和资源计数,可以跨多个任务使用;互斥锁用于保护共享资源, 具有优先级继承机制,主要用于互斥访问。本示例展示的是信号量的同步功能。
本示例中信号量初始值为 0,表示初始无资源,消费者需要等待生产者释放资源。 如果初始值 > 0,则表示初始有可用资源,消费者可以直接获取。
生产者任务优先级为 3,消费者任务优先级为 2。 优先级设置影响任务调度顺序,需要根据实际应用场景合理配置。
当多个任务等待同一个信号量时,阻塞队列按任务优先级排序。 资源释放时,优先唤醒高优先级的等待任务,确保系统的实时性。
深入学习的相关资源