外观
信号量示例
2025-10-29
概述
本文介绍了如何在 RuiChing Studio 中创建一个 ipc_sem 示例工程,并将其编译后在开发板上运行。旨在帮助读者进一步熟悉 RuiChing Studio 开发环境,掌握 信号量的使用。
信号量的作用
在 RT-Thread 中,信号量(Semaphore)是一种核心的线程间同步机制,主要用于解决线程同步、资源互斥、资源计数和事件通知等问题。
运行信号量使用示例
用本示例以运用 RT-Thread 信号量机制实现经典的生产者 - 消费者问题,模拟生产者生产数据和消费者消费数据的过程,确保多线程环境下数据访问的同步与互斥为实践目标,实现生产者线程生产数据存入共享缓冲区,消费者线程从共享缓冲区取出数据,通过信号量控制缓冲区资源的使用,避免数据竞争和缓冲区溢出或空读的演示效果。
(1)生产者线程:
1)获取 1 个空位(放产品 number),此时空位减 1;
2)上锁保护;本次的产生的 number 值为 cnt+1,把值循环存入数组 array 中;再开锁;
3)释放 1 个满位(给仓库中放置一个产品,仓库就多一个满位),满位加 1;
(2)消费者线程:
1)获取 1 个满位(取产品 number),此时满位减 1;
2)上锁保护;将本次生产者生产的 number 值从 array 中读出来,并与上次的 number 值相加;再开锁;
3)释放 1 个空位(从仓库上取走一个产品,仓库就多一个空位),空位加 1。
生产者依次产生 10 个 number,消费者依次取走,并将 10 个 number 的值求和。信号量锁 lock 保护 array 临界区资源:保证了消费者每次取 number 值的排他性,实现了线程间同步。
创建工程点击展开
依次点击 “文件” -> “新建” -> "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 中调用(用于通知任务);
applications/sem_example.c
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;
}
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, "lock", 1, RT_IPC_FLAG_PRIO); // 初始化信号量
rt_sem_init(&sem_empty, "empty", MAXSEM, RT_IPC_FLAG_PRIO); // 初始化信号量
rt_sem_init(&sem_full, "full", 0, RT_IPC_FLAG_PRIO); // 初始化信号量
producer_tid = rt_thread_create("producer", 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("consumer", 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,消费者线程依次取走并计算总和。
rtt 终端
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!