Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
IPC
2024-RSOC
【2024-RSOC】IPC学习分享和调试心得
发布于 2024-07-24 19:57:11 浏览:231
订阅该版
[tocm] # IPC机制 ## 关键词 线程同步,线程间通信,信号量,互斥量,事件集,邮箱,消息队列 ## 临界区 同一时间只能被一个线程使用,但被占用时,其他的线程只能等待 ## 阻塞和非阻塞 **阻塞** 当等待一个事件完成时,我不干别的事情,在等这件事完成,称为阻塞。 **非阻塞** 当等待这个事情完成时,我先去干别的事情,等这件事情完成时会给我发送一个通知,这时我在回来处理这件事情,称为非阻塞。 ## 挂起 将一件事情暂时放下(会将当时的情况保存下来,上下文,栈等),先去干别的事情,等别的事情干完,还可以回来干这件事情 ## 死锁 例如两个线程AB,A在等待B的信号量,B也在等待A的信号量,这就会导致两个人的信号量都得不到释放,就会导致死锁的发生。 ## 信号量 ### 二值信号量 一般用于同步作用 ### 计数信号量 ![screenshot_image-20240724094707054.png](https://oss-club.rt-thread.org/uploads/20240724/96fd836892f34a46f492fa50e7fd9a53.png.webp) ## 互斥量 防止优先级反转 当低优先级获取了高优先级线程的信号量时,低优先级线程的优先级会暂时提高到和高优线线程同样的优先级,防止被其他中优先级的线程给打断 ![screenshot_image-20240724102648663.png](https://oss-club.rt-thread.org/uploads/20240724/7d72daadccd4c9cde3215ae9d3f0e1f7.png.webp) ![screenshot_image-20240724103424652.png](https://oss-club.rt-thread.org/uploads/20240724/a7615de083e1bf275f62f463251097c3.png.webp) 互斥量可以多次获取,但是获取了几次,就得释放几次,释放和获取都必须由同一个线程来进行 ## 事件集 有一个32bit的数,每一位都代表一个事情,可以查看32个事情的状态是否到来 ![screenshot_image-20240724104454431.png](https://oss-club.rt-thread.org/uploads/20240724/d1649c3146542a45a3780e707222e252.png.webp) ![screenshot_image-20240724105455760.png](https://oss-club.rt-thread.org/uploads/20240724/08daaa965a9e4bec24cbf983ecbd3a44.png.webp) 事件集(Event Flags)是实时操作系统中用于线程间通信的一种机制,它提供了一种轻量级的方法来同步多个线程的执行流程。事件集可以看作是一组标志位的集合,线程可以通过设置或清除这些标志位来传达某种状态或条件。 事件集(Event Flags)是 RT-Thread 提供的一种用于线程间同步和通信的工具。它允许线程设置和等待一组特定的标志位,从而协调不同线程之间的活动。事件集适用于需要快速响应和低开销的场景,比如状态通知、条件等待等。 ## 邮箱 每一个邮箱的大小为四字节,在32位系统中,可以发送指针或者数值 邮箱的底层是数组,相比消息队列的链表来说,更小更轻便 ### 函数 动态创建和删除 ```c /** * @brief 创建并初始化一个消息邮箱 * * @attention 用户必须在使用前确保有足够的内存用于消息邮箱的创建。 * * @param[in] name 消息邮箱的名称,用于标识和调试。 * @param[in] size 消息邮箱的最大容量,即最多可以存储的消息数量。 * @param[in] flag 创建时的标志位,可以用来指定邮箱的某些特性(如消息排序方式)。 * * @return 如果创建成功,返回一个指向新创建的消息邮箱的句柄; * 否则,返回 RT_NULL 或者一个错误码,具体取决于 RT-Thread 的配置。 * * @ingroup RTTHREAD_MBOX */ rt_mailbox_t rt_mb_create(const char* name, rt_size_t size, rt_uint8_t flag); rt_err_t rt_mb_delete (rt_mailbox_t mb); ``` 初始化邮箱和脱离 ```c rt_err_t rt_mb_init(rt_mailbox_t mb, const char* name, void* msgpool, rt_size_t size, rt_uint8_t flag) ``` | **参数** | **描述** | | -------- | ------------------------------------------------------------ | | mb | 邮箱对象的句柄 | | name | 邮箱名称 | | msgpool | 缓冲区指针 | | size | 邮箱容量 | | flag | 邮箱标志,它可以取如下数值: RT_IPC_FLAG_FIFO 或 RT_IPC_FLAG_PRIO | | **返回** | —— | | RT_EOK | 成功 | ```c rt_err_t rt_mb_detach(rt_mailbox_t mb); ``` | **参数** | **描述** | | -------- | -------------- | | mb | 邮箱对象的句柄 | | **返回** | —— | | RT_EOK | 成功 | 发送邮件 ```c rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value); ``` | **参数** | **描述** | | --------- | -------------- | | mb | 邮箱对象的句柄 | | value | 邮件内容 | | **返回** | —— | | RT_EOK | 发送成功 | | -RT_EFULL | 邮箱已经满了 | 发送紧急邮件(发送的邮箱会排在队首) ```c rt_err_t rt_mb_urgent (rt_mailbox_t mb, rt_ubase_t value); ``` ```c rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);复制错误复制成功 ``` 接收邮件 接收者需指定接收邮件的邮箱句柄,并指定接收到的邮件存放位置以及最多能够等待的超时时间。如果接收时设定了超时,当指定的时间内依然未收到邮件时,将返回 - RT_ETIMEOUT。下表描述了该函数的输入参数与返回值: | **参数** | **描述** | | ------------ | -------------- | | mb | 邮箱对象的句柄 | | value | 邮件内容 | | timeout | 超时时间 | | **返回** | —— | | RT_EOK | 接收成功 | | -RT_ETIMEOUT | 超时 | | -RT_ERROR | 失败,返回错误 | ## 消息队列 消息 消息是在线程间传递的数据单元。它可以是任意类型的数据,但通常会被封装成一个结构体,包含消息类型和数据字段。 ### 队列 消息队列是一个先进先出(FIFO)的数据结构,用于存储消息。队列具有固定的大小,由创建时设定,一旦队列满载,新的消息将不能被加入,直到有消息被读取。 ### 创建消息队列 在 RT-Thread 中,消息队列可以通过 `rt_mq_create` 或 `rt_mq_init` 函数来创建或初始化。 ### 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); ``` - `name`: 消息队列的名称,用于调试和系统管理。 - `length`: 队列的最大消息数量。 - `msgsize`: 每条消息的大小。 - `flag`: 创建时的标志位,用于控制队列行为。 ### rt_mq_init ``` rt_err_t rt_mq_init(rt_mq_t mq, const char* name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag); ``` - `mq`: 指向消息队列的指针。 - `name`: 消息队列的名称。 - `msgpool`: 消息缓冲区的起始地址。 - `pool_size`: 队列的最大消息数量。 - `msg_size`: 每条消息的大小。 - `flag`: 创建时的标志位。 ### 使用消息队列 ### 发送消息 使用 `rt_mq_send` 或 `rt_mq_send_wait` 函数发送消息到队列。 #### rt_mq_send ``` rt_err_t rt_mq_send (rt_mq_t mq, void* buffer, rt_size_t size); ``` #### rt_mq_send_wait ``` rt_err_t rt_mq_send_wait(rt_mq_t mq, const void *buffer, rt_size_t size, rt_int32_t timeout); ``` ### 接收消息 使用 `rt_mq_recv` 或 `rt_mq_recv_wait` 函数从队列接收消息。 #### rt_mq_recv ``` rt_err_t rt_mq_urgent(rt_mq_t mq, void* buffer, rt_size_t size); ``` #### rt_mq_recv_wait ``` rt_ssize_t rt_mq_recv (rt_mq_t mq, void* buffer,rt_size_t size, rt_int32_t timeout); ``` ## 调试心得 1. **信号量(Semaphore)** - 信号量用于控制对共享资源的访问数量。在调试时,关注信号量的计数变化,避免死锁,如果有可能会导致优先级反转的情况,要使用互斥量。 2. **互斥量(Mutex)** - 互斥量保证同一时刻只有一个线程可以访问特定资源。调试时,检查锁的获取与释放是否成对出现,防止出现其他线程一直获取不到信号量。 3. **事件集(Event Set)** - 事件集通常用于通知机制,一个线程可以设置事件,而其他线程等待这些事件被触发。调试时,确保所有等待的线程最终都能收到事件通知,避免无限等待,不要忘记添加清除标记。 4. **邮箱(Mailbox)** - 邮箱是进程间通信的一种方式,允许发送和接收消息,但是只能发送四字节。调试时,检查消息是否正确无误地发送和接收,避免消息丢失或顺序错误。 5. **消息队列(Message Queue)** - 消息队列提供了一种先进先出的数据结构来存储和传递消息。在调试时,注意队列的长度限制,以及消息的入队和出队操作是否正确,防止队列溢出或下溢。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
murnure
这家伙很懒,什么也没写!
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
1
请问线程休眠时清除 errno 的设计意图是什么?
2
ipc对象插入时既有优先级模式,又有ffio模式会不会出bug?
3
我自己添加一个释放多个信号量的函数,会不会对系统有影响
4
rtthread IPC机制理解
5
如何实现多个线程对1个线程消息的订阅
6
请问Nano怎么使用IPC组件,是不是必须标准版才可以使用
7
RTT 多线程间通信机制有哪几种及推荐?
8
对于动态申请的IPC(邮箱,信号量),如何确保在释放的时候临界安全问题
9
调用rt_sem_take前是否要先发送RT_IPC_CMD_RESE...
10
驱动程序中的线程挂起与IPC的线程挂起流程为什么不一样?
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部