外观
信号量示例
2026-05-15
概述
本文介绍如何在 睿擎工业开发平台 中创建并运行 信号量 示例工程,通过初始化三个信号量(互斥锁、空位计数、满位计数)和两个线程,模拟经典的“生产者-消费者”模型。代码通过信号量的获取与释放,实现了对环形缓冲区(共享资源)的安全访问与线程间的同步协调,帮助读者快速掌握信号量这一核心线程间同步机制的使用方法。
信号量简介
信号量(semaphore)是一种经典的线程间同步与互斥机制,通过计数器来控制对共享资源的访问。它允许线程在资源可用时获取信号量,在资源处理完毕后释放信号量,从而实现对临界区的保护以及线程间的协调。信号量在嵌入式开发中被广泛应用于任务调度、共享资源锁定以及生产者-消费者等协作场景。
构建与烧录
创建工程点击展开
依次点击 “文件” -> “新建” -> "RT-Thread RuiChing App 项目"。

在弹出新建向导中选择 开发版 、BSP: 、示例 、 调试器/下载器。选择好之后点击 “完成”。

点击 “完成” 后,等待工程创建完成。

创建完成。

构建工程点击展开
单击工程使工程进入 Active-Debug 模式。

点击工具栏上的构建按钮进行工程编译。

构建成功后,会显示构建成功的信息。

固件下载点击展开
固化驱动

固化 APP

核心示例代码
信号量示例相关 API
rt_sem_init:信号量初始化,value=0时作为事件通知,value=1时作为互斥锁,value>1时作为资源计数器rt_sem_take:获取信号量,若 value > 0,立即返回成功,value--;否则阻塞线程,超时控制,不可在中断服务程序(ISR)中调用rt_sem_release:释放信号量,value++,并唤醒等待队列中的线程,根据 flag(PRIO 或 FIFO)选择唤醒优先级最高的线程,可在 ISR 中调用(用于通知任务)rt_sem_detach:脱离信号量,该函数将把指定的静态信号量从内核对象管理器中移除。参数为 sem(指定的信号量对象),若脱离成功返回 RT_EOK
sem_example.c
static void _producer_thread_entry(void *parameter)
{
int cnt = 0;
while (cnt < 10)
{
rt_sem_take(&_sem_empty, RT_WAITING_FOREVER);//获取信号量
rt_sem_take(&_sem_lock, RT_WAITING_FOREVER);//获取信号量
_array[_set % MAXSEM] = cnt + 1;
rt_kprintf("the producer generates a number: %d\n",
_array[_set % MAXSEM]);
_set++;
rt_sem_release(&_sem_lock);//释放信号量
rt_sem_release(&_sem_full);//释放信号量
cnt++;
rt_thread_mdelay(20);
}
rt_kprintf("the producer exit!\n");
cnt = 0;
}
static void _consumer_thread_entry(void *parameter)
{
rt_uint32_t sum = 0;
while (1)
{
rt_sem_take(&_sem_full, RT_WAITING_FOREVER);//获取信号量
rt_sem_take(&_sem_lock, RT_WAITING_FOREVER);//获取信号量
sum += _array[_get % MAXSEM];
rt_kprintf("the consumer[%d] get a number: %d\n", (_get % MAXSEM),
_array[_get % MAXSEM]);
_get++;
rt_sem_release(&_sem_lock);//释放信号量
rt_sem_release(&_sem_empty);
if (_get == 10)
{
break;
}
rt_thread_mdelay(50);
}
rt_kprintf("the consumer sum is: %d\n", sum);
rt_kprintf("the consumer exit!\n");
rt_sem_detach(&_sem_lock);//脱离信号量
rt_sem_detach(&_sem_empty);//脱离信号量
rt_sem_detach(&_sem_full);//脱离信号量
sum = 0;
}
int semaphore_producer_consumer_example(void)
{
rt_thread_t producer_tid = RT_NULL;
rt_thread_t consumer_tid = RT_NULL;
_set = 0;
_get = 0;
rt_sem_init(&_sem_lock, SEM_LOCK_NAME, 1, RT_IPC_FLAG_PRIO);//初始化信号量//
rt_sem_init(&_sem_empty, SEM_EMPTY_NAME, MAXSEM, RT_IPC_FLAG_PRIO);//初始化信号量//
rt_sem_init(&_sem_full, SEM_FULL_NAME, 0, RT_IPC_FLAG_PRIO);//初始化信号量//
producer_tid = rt_thread_create(THREAD1_NAME, _producer_thread_entry,
RT_NULL, THREAD_STACK_SIZE,
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
if (producer_tid != RT_NULL)
{
rt_thread_startup(producer_tid);
}
else
{
rt_kprintf("create thread producer failed");
return -1;
}
consumer_tid = rt_thread_create(THREAD2_NAME, _consumer_thread_entry,
RT_NULL, THREAD_STACK_SIZE,
THREAD_PRIORITY + 1, THREAD_TIMESLICE);
if (consumer_tid != RT_NULL)
{
rt_thread_startup(consumer_tid);
}
else
{
rt_kprintf("create thread consumer failed");
return -1;
}
return 0;
}运行示例
操作步骤
- 将程序下载到开发板
- 打开串口终端连接开发板
- 输入
semaphore_producer_consumer_example命令
预期结果
生产者线程依次产生 10 个 number,消费者线程依次取走并计算总和。
RT-Thread 终端
msh />semaphore_producer_consumer_example
the producer generates a number: 1
the consumer[0] get a number: 1
the producer generates a number: 2
the producer generates a number: 3
the consumer[1] get a number: 2
the producer generates a number: 4
the producer generates a number: 5
the producer generates a number: 6
the consumer[2] get a number: 3
the producer generates a number: 7
the producer generates a number: 8
the consumer[3] get a number: 4
the producer generates a number: 9
the consumer[4] get a number: 5
the producer generates a number: 10
the producer exit!
the consumer[0] get a number: 6
the consumer[1] get a number: 7
the consumer[2] get a number: 8
the consumer[3] get a number: 9
the consumer[4] get a number: 10
the consumer sum is: 55
the consumer exit!