RT-Thread----线程间通信 (IPC)
摘要:RTOS提供三种IPC机制解决多线程通信问题:1)邮箱(Mailbox)实现高效"零拷贝"传输,通过传递4字节数据或指针,适合大数据传输;2)消息队列(MessageQueue)采用深拷贝方式传输数据块,安全性高但效率较低;3)信号(Signal)作为软中断机制,用于异步异常处理。邮箱适合大数据传输,消息队列适合小结构体传输,信号仅建议用于异常处理场景。开发者应根据数据传
前言:
在多线程系统中,全局变量虽然简单,但存在 数据撕裂(不安全)、无通知机制(低效轮询) 和 高耦合 三大弊端。
RTOS 提供了专业的 IPC 机制来解决这些问题:
传输数据:使用 邮箱 (Mailbox) 或 消息队列 (Message Queue)。
控制流/异常:使用 信号 (Signal)。
第一部分:邮箱 (Mailbox) —— 极速传“键”
1. 核心概念
-
本质:RTOS 中最高效的通信方式,固定传输 4 字节(32位系统下)。
-
载荷:只能容纳一个
rt_ubase_t类型(无符号长整型)。-
传值:直接传递状态码(如
100,0xFF)。 -
传址(核心用法):传递大数据的内存地址(指针),实现**“零拷贝”**。
-
-
缓冲:有固定深度的邮件池,发不进去或收不到可以挂起等待。
2. API 详解
(1) 创建邮箱 rt_mb_create
rt_mailbox_t rt_mb_create(const char *name,
rt_size_t size,
rt_uint8_t flag);
-
name: 邮箱名称(用于调试)。 -
size: 容量。指能存放多少封邮件(多少个 4 字节),而不是指字节数。 -
flag: 排队模式。-
RT_IPC_FLAG_FIFO(推荐):先来先服务。 -
RT_IPC_FLAG_PRIO:按优先级排队。
-
(2) 发送邮件 rt_mb_send
rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value);
-
mb: 邮箱句柄。 -
value: 邮件内容(4字节)。-
如果是数字:直接填
100。 -
如果是指针:需要强制转换
(rt_ubase_t)ptr。
-
(3) 接收邮件 rt_mb_recv
rt_err_t rt_mb_recv(rt_mailbox_t mb,
rt_ubase_t *value,
rt_int32_t timeout);
-
mb: 邮箱句柄。 -
value: 接收缓存的地址。系统会把邮件内容写到这个变量里。 -
timeout: 等待时间。-
RT_WAITING_FOREVER: 死等(最常用,没信就睡觉)。 -
0: 不等,没信直接返回错误。
-
(4) 删除邮箱 rt_mb_delete
rt_err_t rt_mb_delete(rt_mailbox_t mb);
-
注意:如果动态申请了数据内存(
malloc),删除邮箱前必须确保数据已处理或释放,否则内存泄漏。
3. “零拷贝”模式(传指针)流程
-
生产者:
rt_malloc申请结构体内存 -> 填数据 ->rt_mb_send发送指针。 -
消费者:
rt_mb_recv接收指针 -> 强转为结构体 -> 读数据 ->rt_free释放内存。-
警示:必须谁受益谁买单(消费者释放),且必须成对出现。
-
第二部分:消息队列 (Message Queue) —— 稳健传“货”
1. 核心概念
-
本质:通过 “深拷贝” (Deep Copy) 传输数据块。
-
载荷:大小可自定义(如 10字节、128字节),发送时将源数据完整复印一份到队列缓冲区。
-
安全性:发送完后,源数据(如局部变量)可以立即销毁,互不影响。
-
缺点:因为涉及
memcpy,数据量大时(如 >1KB)效率远低于邮箱。
2. API 详解
(1) 创建队列 rt_mq_create
rt_mq_t rt_mq_create(const char *name,
rt_size_t msg_size,
rt_size_t max_msgs,
rt_uint8_t flag);
-
msg_size: 每条消息的大小(字节)。建议用sizeof(struct MyData)。 -
max_msgs: 队列深度。最多能缓存多少条消息。 -
flag: 排队模式 (FIFO/PRIO)。
(2) 发送消息 rt_mq_send
rt_err_t rt_mq_send(rt_mq_t mq,
void *buffer,
rt_size_t size);
-
mq: 队列句柄。 -
buffer: 数据源指针。你要发送的数据在哪里? -
size: 数据长度。通常等于创建时的msg_size。
(3) 发送紧急消息 rt_mq_urgent
rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size);
-
特权:这条消息会插队到队列的最前面,消费者下次读取时最先读到它。
-
场景:发送“停止”命令。
(4) 接收消息 rt_mq_recv
rt_err_t rt_mq_recv(rt_mq_t mq,
void *buffer,
rt_size_t size,
rt_int32_t timeout);
-
mq: 队列句柄。 -
buffer: 接收缓冲区。必须指向一块足够大的内存(通常是栈上的局部变量)。 -
size: 缓冲区大小。
第三部分:信号 (Signal) —— 强制通知(冷门但霸道)
1. 核心概念
-
本质:软中断。用于模拟操作系统层面的中断行为。
-
特点:异步。接收线程无需调用接收函数,信号一来,线程立刻被打断(类似中断服务函数),强行跳转去处理信号。
-
用途:异常处理(除零错)、杀线程、极低频的控制命令。不适合传输数据。
2. 核心 API
(1) 发送信号 rt_thread_kill
int rt_thread_kill(rt_thread_t thread, int sig);
-
thread: 目标线程的句柄(ID)。 -
sig: 信号编号。-
系统保留:
SIGKILL(强制杀死),SIGSTOP等。 -
用户自定义:
SIGUSR1,SIGUSR2。
-
(2) 安装信号处理函数 rt_signal_install
rt_sighandler_t rt_signal_install(int sig, rt_sighandler_t handler);
-
告诉系统:当收到
sig这个信号时,请自动执行handler这个函数。
第四部分:选型总结(一张表)
| 特性 | 邮箱 (Mailbox) | 消息队列 (Msg Queue) | 信号 (Signal) |
| 传输内容 | 4 字节 (数值/地址) | 数据块 (结构体) | 信号编号 (整数) |
| 机制 | 零拷贝 (传指针) | 深拷贝 (memcpy) | 软中断 (异步跳转) |
| 内存管理 | 需用户 malloc/free |
系统自动管理缓冲区 | 无 |
| 安全性 | 需警惕野指针 | 高 (数据隔离) | / |
| 适用场景 | 大数据传指针、状态码 | 传感器数据包、串口命令 | 异常处理、紧急控制 |
| 一句话建议 | 追求极速或传大数据时用 | 传小结构体最省心,首选 | 除非处理异常,否则别用 |
更多推荐



所有评论(0)