Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024——RSOC】 rtthread 内核-IPC的学习
发布于 2024-07-25 20:39:36 浏览:399
订阅该版
[tocm] # IPC学习总结 ## 线程同步 + 信号量 + 互斥量 + 事件集 ## 线程通信 + 邮箱 + 消息队列 ## 信号量 信号量(Semaphore)是一种轻型的用于解决线程间同步问题的内核对象,一个或多个运行线程可 以获取或释放它,从而达到同步或互斥的目的。用于实现任务与任务之间、任务与中断处理程序 之间的同步与互斥。 • 信号量一般分为种: + **二进制信号量(Binary Semaphore)**:只有两个状态(0和1),常用于互斥访问。 - **计数信号量(Counting Semaphore)**:允许多个线程同时访问共享资源,但是通过计数进行控制。 • 将信号量进行种类细分,可以根据其用途,在具体实现时做专门处理,提高执行效率和可靠性 ### 信号量API #### 信号量控制块 ```C struct rt_semaphore{ struct rt_ipc_object parent; /**< inherit from ipc_object */ rt_uint16_t value; /**< value of semaphore. */ rt_uint16_t reserved; /**< reserved field */ }; ``` ### 信号量操作 #### 创建 ```c /* 参数的含义: 1、name 信号量名称 2、value 信号量初始值 3、flag 信号量标志, */ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) ``` #### 删除 ```c /* 参数: sem 信号量句柄 */ rt_err_t rt_sem_delete(rt_sem_t sem) ``` #### 初始化 ```c 参数的含义: 1、sem 信号量对象的句柄 2、name 信号量名称 3、value 信号量初始值 4、flag 信号量标志 rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag) ``` #### 脱离 ```C 参数: sem 信号量对象的句柄 rt_err_t rt_sem_detach(rt_sem_t sem); ``` #### 获取信号量 `rt_err_t rt_sem_take(rt-sem_t sem,rt_int32_t time)` `sem : 信号量对应句柄` `time: 等待时间` `rt_err_t rt_sem_trytake(rt-sem_t sem);` `无需等待获取` ## 互斥量 互斥量又叫相互排斥的信号量,是一种特殊的二值信号量。 它和信号量不同的是,它支持: 1. 互斥量所有权; 2. 递归访问; 3. 防止优先级翻转的特性 ### API #### 创建 `rt_mutex_t rt-mutex_create(const char *name ,rt_uint8_t flag);` 调用 rt_mutex_create 函数创建一个互斥量,它的名字由 name 所指定。当调用这个函数时,系 统将先从对象管理器中分配一个 mutex 对象,并初始化这个对象,然后初始化父类 IPC 对象以及 与 mutex 相关的部分。互斥量的 flag 标志已经作废,无论用户选择 RT_IPC_FLAG_PRIO 还是 RT_IPC_FLAG_FIFO,内核均按照 RT_IPC_FLAG_PRIO 处理。 #### 删除 `rt_err_t rt_mutex_delete(rt_mutex_t mutex);` 当不再使用互斥量时,通过删除互斥量以释放系统资源,适用于动态创建的互斥量。 当删除一个互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是 - RT_ERROR。 然后系统将该互斥量从内核对象管理器链表中删除并释放互斥量占用的内存空间. #### 初始化 `rt_err_t rt_mutex_init(rt_mutex_t mutex,const char * name,rt_uint8_t flag);` 静态互斥量对象的内存是在系统编译时由编译器分配的,一般放于读写数据段或未初始化数据段中。 在使用这类静态互斥量对象前,需要先进行初始化。 使用该函数接口时,需指定互斥量对象的句柄(即指向互斥量控制块的指针),互斥量名称以及互斥 量标志。互斥量标志可用上面创建互斥量函数里提到的标志。 #### 脱离 `rt_err_t rt_mutex_detach(rt_mutex_t mutex);` 当使用该函数接口后,内核先唤醒所有挂在该互斥量上的线程(线程的返回值是 -RT_ERROR),然后 系统将该互斥量从内核对象管理器中脱离. #### 获取 `rt_err_t rt_mutex_take(rt_mutex_t mutex,rt_uint8_t time);` 线程获取了互斥量,那么线程就有了对该互斥量的所有权,即某一个时刻一个互斥量只能被一个线程 持有。 如果互斥量没有被其他线程控制,那么申请该互斥量的线程将成功获得该互斥量。如果互斥量已经被 当前线程线程控制,则该互斥量的持有计数加 1,当前线程也不会挂起等待。如果互斥量已经被其他 线程占有,则当前线程在该互斥量上挂起等待,直到其他线程释放它或者等待时间超过指定的超时时 间。 #### 无等待获取 `rt_err_t rt_mutex_trytake(rt_mutex_t mutex);` 线程获取了互斥量,那么线程就有了对该互斥量的所有权,即某一个时刻一个互斥量只能被一个线程 持有。 如果互斥量没有被其他线程控制,那么申请该互斥量的线程将成功获得该互斥量。如果互斥量已经被 当前线程线程控制,则该互斥量的持有计数加 1,当前线程也不会挂起等待。如果互斥量已经被其他 线程占有,则当前线程在该互斥量上挂起等待,直到其他线程释放它或者等待时间超过指定的超时时 间. #### 释放 `rt_err_t rt_mutex_release(rt_mutex_t mutex);` 线程获取了互斥量,那么线程就有了对该互斥量的所有权,即某一个时刻一个互斥量只能被一个线程 持有。 如果互斥量没有被其他线程控制,那么申请该互斥量的线程将成功获得该互斥量。如果互斥量已经被 当前线程线程控制,则该互斥量的持有计数加 1,当前线程也不会挂起等待。如果互斥量已经被其他 线程占有,则当前线程在该互斥量上挂起等待,直到其他线程释放它或者等待时间超过指定的超时时 间 ## 事件集 ##### 事件集是一个32bit的书,每个事件用一个bit位代表 ### 接收事件 rt_err_t rt_event_recv(rt_event_t event , rt uint32_t set , rt_uint8_t option ,rt_int32_t, timeout ,rt_uint32_t* recved); ## 消息邮箱(mailbox) ##### rtthread的邮箱用于线程间的通信,特点是开销低,效率高。每一封邮件容纳4字节内容(对应32位处理系统,一个指针)。 ### API #### 创建 rt_mailboc_create(const char * name ,rt-size_t size, rt_uint8_t flag); 1.分配邮箱对象 2.动态分配空间(内存大小 = 邮件大小*4字节) #### 删除 rt_err_t rt_=mb_delete(rt_mailbox_t mb); #### 初始化 rt_err_t rt_mb_init(rt_mailbox_t mb, const char * name ,void * msgpool , rt_size_t size); #### 发送邮箱 rt_err_t rt_mb_send(rt_mailbox mb,rt_uint32_t value); #### 脱离邮箱 rt_err_t rt_mb_send(rt_mailbox_t mb, rt_uin) #### 等待方式方式邮件(不允许中断使用) rt_err_t rt-mb_send_wait(rt_mailbox_t mb rt_uint32_t value rt_uint32_t timeout); #### 发送紧急邮件 rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase value); #### 接收邮件 rt_mb_recv(rt_mailbox mb,rt_uint32_t* timeout ); ## 消息队列 ##### 消息队列,也就是将多条消息排成的队列形式,是一种常用的线程间通信 方式,可以应用在多种场合,线程间的消息交换,使用串口接收不定长数据等。线 程可以将一条或多条消息放到消息队列中,同样一个或多个线程可以从消息队列中 获得消息;同时消息队列提供异步处理机制可以起到缓冲消息的作用。 ### 特性 + 支持读消息超时机制 + 支持等待方式发送消息 + 允许不同长度 + 支持发送紧急消息 ![image-20240725202504568](C:\Users\27545\AppData\Roaming\Typora\typora-user-images\image-20240725202504568.png) ### 消息队列创建 创建消息队列时先从对象管理器中分配一个消息队列对象,然后给消息队列对象分配一块 内存空间,组织成空闲消息链表,这块内存的大小 = **[消息大小 + 消息头(用于链表连接)** **的大小**] * **消息队列最大个数**,接着再初始化消息队列;接口返回RT_EOK表示动态消息队 列创建成功。 rt_mq_t rt-mq_create(const char *name , rt_size_t msg_size,rt_size_t max_msgs,rt_uint8_t flag); #### 消息队列参数flag 在创建消息队列指定的参数中,事件集标志参数决定了当消息不可获取时,多个线程等待的排 队方式。 + 当选择 RT_IPC_FLAG_FIFO(先进先出)方式时,那么等待线程队列将按照先进先出 的方式排队,先进入的线程将先获得等待的消息; + 当选择 RT_IPC_FLAG_PRIO(优先级等待)方式时,等待线程队列将按照优先级进行 排队,优先级高的等待线程将先获得等待的消息 #### 发送消息 线程或者中断服务程序都可以给消息队列发送消息。当发送消息时,消息队列对象先从空闲 消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上, 然后把该消息块挂到消息队列的尾部。当且仅当空闲消息链表上有可用的空闲消息块时,发 送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送 消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。发送消息的函数接口如下: `rt_err_t rt_mq——森达(rt_mq_t mq,void * buffer,rt-size_t size);` + mq;消息队列句柄 + buffer;消息内容 + size : 消息大小 #### 等待的方式发送消息 等待发送消息的函数接口如下,rt_mq_send_wait() 与 rt_mq_send() 的区别在于有等待时 间,如果消息队列已经满了,那么发送线程将根据设定的 timeout 参数进行等待。如果设 置的超时时间到达依然没有空出空间,这时发送线程将被唤醒并返回错误码 rt_err_t rt_mq_send_wait(rt-qr_t目前,const void * buffer,rt_size_t size , rt_uint32_t timeout ); + mq:消息队列句柄 + buffer:消息内容 + size: 消息大小 + timeout ; 超时时间 #### 发送紧急消息 发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,从空闲消 息链表上取下来的消息块不是挂到消息队列的队尾,而是挂到队首,这样,接收者就能够 优先接收到紧急消息,从而及时进行消息处理。发送紧急消息的函数接口如下; `rt_err- t rt_mq-urgent(rt_mq_t mq,void * buffer,rt_size-t size);` #### 接收消息 当消息队列中有消息时,接收者才能接收消息,否则接收者会根据超时时间设置,或挂起在 消息队列的等待线程队列上,或直接返回。接收消息函数接口如下; rt_err_t rt_mq_recv(rt_mq_t mq,void *buffer , rt_size_t size ,rt_uint32_t timeout)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
才淇高理
这家伙很懒,什么也没写!
文章
6
回答
1
被采纳
0
关注TA
发私信
相关文章
推荐文章
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
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部