Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
【2024-RSOC】Day03 线程同步与线程间通信
发布于 2024-07-24 22:37:47 浏览:253
订阅该版
[tocm] # 线程-IPC机制 ## 重要概念 ### 临界资源和临界区 1. 临界资源:多个线程或进程共同访问的资源,但是每次只能有一个线程或进程使用,以避免冲突。这些资源可能是物理设备(如打印机、磁盘等),也可能是软件中的某些数据(如共享变量、文件等)。 2. 临界区:一个访问共享资源的代码区域,这些共享资源一次只能由一个线程访问,否则可能会导致数据不一致或冲突。 ### 阻塞Block与非阻塞 当一个线程占用了临界资源,那么其他线程就必须等待临界资源被释放。这种由于临界资源被占用而处于等待的状态叫做线程阻塞。 ### 挂起/暂停Suspend 线程挂起是指把线程脱离就绪队列,使线程不参与调度器的调度。即线程被暂停执行,但不会立即释放其所占用的资源(如锁、信号量等),直到它被显式地恢复(Resume)为止。 线程挂起是用户主动控制的,可以通过特定的接口函数(如rt_thread_suspend())来实现。挂起时,线程不会释放对象锁或其他资源。 挂起状态与线程阻塞不同,挂起是用户显式控制的,而阻塞则是由某些事件或条件触发的。线程状态切换示意图如下。 ![10线程状态的切换.PNG](https://oss-club.rt-thread.org/uploads/20240724/b500dd0fa4758f2eb1f127da2d1e600a.png.webp) ### 死锁问题 线程因为资源竞争,彼此需要资源又都无法释放,导致线程无法获取下一步执行所需的资源,从而产生死锁。 ## 线程同步的三种方法 信号量、互斥量和事件集 ### 信号量semaphore 在裸机程序中使用全局变量flag来同步的问题: 内存写穿时,flag的值被篡改;没有阻塞-挂起机制,在等待flag的过程中,CPU一直在空等,降低效率。 #### 信号量的类型 1. 二值信号量 用于解决同步问题:用于线程与线程,线程与中断服务程序ISR的同步 初始值:0或1 二值信号量的状态转换图 ![11二值信号量的状态装换图.PNG](https://oss-club.rt-thread.org/uploads/20240724/7574e7076f899933691a60106040e4a1.png.webp) 2. 计数信号量 用于解决计数问题:初始化为n-非负数,n为共享资源的数量 计数信号量状态转换图 ![12计数信号量的状态转换图.PNG](https://oss-club.rt-thread.org/uploads/20240724/f2f41a745ddda308eae832c2125818ea.png.webp) #### 信号量的API 1. 创建/初始化 动态创建,好处:节省资源;弊处:可能会有内存写穿 ```c rt_sem_t rt_sem_create(const char *name, //信号量的名称 rt_uint32_t value, //信号量的初始值 rt_uint8_t flag) ``` 信号量的标志参数-决定多个线程的排队方式: 先进先出 RT_IPC_FLAG_FIFO 优先级等待 RT_IPC_FLAG_PRIO 其中rt_sem_t(信号量的控制块指针)的原型如下: ```c struct rt_semaphore { struct rt_ipc_object parent; /**< inherit from ipc_object */ rt_uint16_t value; /**< value of semaphore. */ rt_uint16_t max_value; struct rt_spinlock spinlock; }; typedef struct rt_semaphore *rt_sem_t; ``` 静态创建 好处:稳健性好,不会被破坏;不使用该信号量,它也会占用资源 ```c rt_err_t rt_sem_init(rt_sem_t sem, //信号量控制块的指针/信号量对象的句柄 const char *name, //信号量名称 rt_uint32_t value, //型号量初始值 rt_uint8_t flag) ``` 2. 删除/脱离 删除信号量-用于动态创建的信号量 ```c rt_err_t rt_sem_delete(rt_sem_t sem) ``` 脱离detatch ```c rt_err_t rt_sem_detatch(rt_sem_t sem) ``` 3. 获取/释放 等待时间,单位OS_Tick,分为三种情况:直接返回RT_WAITING_NO,挂起并等待一段时间,挂起并永远等待直到获取到信号量 ```c rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time) ``` 4. 释放信号量 每释放一个信号量,就唤醒挂起在该信号量上的一个线程(先进先出,按优先级) ```c rt_err_t rt_sem_release(rt_sem_t sem) ``` ### 互斥量mutex 特殊的二值信号量,它支持:互斥量的所有权(哪个线程先获取到互斥量,其他线程就不能获取),递归访问,防止优先级反转的特性 #### 优先级反转问题Priority Inversion ![13优先级反转问题.PNG](https://oss-club.rt-thread.org/uploads/20240724/a7ef293a66cf2dc0dd4bd1274b93f5bc.png.webp) 优先级A(M) > B > C(M),A和B处于就绪态,等待某事件发生, C占用共享资源M,B不需要共享资源M。B先于A执行 #### 解决方法:优先级继承 ![14优先级继承.PNG](https://oss-club.rt-thread.org/uploads/20240724/8645afa9a286b92530cfebb52afe2bf3.png.webp) 互斥量可以解决优先级反转的问题 提高某个占用共享资源M的低优先级线程C的优先级,使得它的优先级等于所有该资源M的线程中最高级的线程的优先级;然后执行C,等C释放共享资源后,C的优先级回到初始态。 #### 互斥量的API函数 互斥量的flag: RT_IPC_FLAG_PRIO,不需要赋初值 1. 动态创建create与删除delete 2. 初始化互斥量init与脱离detatch 3. 获取take/释放release 某一时刻一个互斥量只能被一个线程持有 无等待获取互斥量trytake(rt_mutex_t mutex) 4. 释放release 当线程thread_1完成互斥资源的访问后,应该尽快释放它占用的互斥量M1 例如:take了5次,只释放了4次,那么thread_1仍然占有M1,其他线程无法访问。上锁和解锁只能由thread_1来操作。当M1的持有计数值为0时,等待M1的线程才会从挂起中唤醒 ### 事件集 事件集是一个32bit的数,每个bit表示一个事件的状态 0-事件发生,1-事件未发生 触发方式:或触发,与触发 ![15事件集的示意图.PNG](https://oss-club.rt-thread.org/uploads/20240724/5ed7ec678f47dbe53406736a66aa0161.png.webp) 事件集的作用如下图所示 ![16事件集的作用.PNG](https://oss-club.rt-thread.org/uploads/20240724/aa2013bf7ae1a4e8675fa5c1a2f95b64.png.webp) #### 事件集API 1. 动态创建create与删除delete rt_event_t rt_event_create() ```c rt_err_t rt_event_delete(rt_event_t event) ``` 2. 初始化互斥量init与脱离detatch 3. 获取take/释放release 4. 发送事件send-接收recv 无符号32位整数rt_uint32_t set = 0x01 send recv 参数option-设置触发方式:或,与触发 ## 线程间通信的两种方法 消息邮箱和消息队列 ### 消息邮箱mailbox 优点:开销低,效率高。 每封邮件只能容纳4Byte内容(32位CPU,指针的大小为4Byte) #### 消息邮箱的API 1. 创建create与删除delete ```c rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag) ``` 2. 初始化邮箱与脱离detatch 静态邮箱对象的内存是在系统编译时由编译器分配的 3. 发送邮件send与接收recv 普通发送:rt_mb_send 等待方式发送邮件(会造成阻塞的API,_wait)不能用到中断函数中 发生紧急邮件: rt_mb_urgent,邮件被直接插入到队首 ### 消息队列msgq 进程间通信,使用串口接收不定长的数据等,消息队列提供异步处理机制-数据缓冲,直接传递数据本身,而消息邮箱传递的是数据的指针。 ##### 消息队列的特性 支持读消息超时机制 支持等待方式发送消息 允许收发不同长度(一条消息的最大长度:不超过队列节点最大值)、多条消息,任意类型的消息 支持发送紧急消息 #### 消息队列的API 1. 创建create rt_mq_t rt_mq_create(名称, 消息长度,个数,等待方式) ```c rt_mq_t rt_mq_create(const char *name, rt_size_t msg_size, //一条消息的最大长度,单位:Byte rt_size_t max_msgs, //消息队列的最大个数 rt_uint8_t flag); //消息队列的等待方式 ``` 2. 发送消息send ```c rt_err_t rt_mq_send(rt_mq_t mq, //消息队列对象的句柄 const void *buffer, //消息内容 rt_size_t size); //消息大小 ``` 3. 接收消息rt_mq_recv ## 实操 ### ENV配置 ![02.PNG](https://oss-club.rt-thread.org/uploads/20240724/c15667081864b8e8b1743ada5b84237c.png) online packages->msc杂项->samples: kernel and components samples-> 勾选kernel thread ESC 退出配置界面,保存设置 pkgs --update //将online packages下载到本地 ![05.PNG](https://oss-club.rt-thread.org/uploads/20240724/8c5f1e6103a15c56827db0b05bd9df73.png) 下载到了本地的packages文件夹中 ![06.PNG](https://oss-club.rt-thread.org/uploads/20240724/a904391b622e0b45229097440e1cdf7d.png) 再次编译 scons -j12 烧录运行 ![04.PNG](https://oss-club.rt-thread.org/uploads/20240724/f4f95f7690cfc2945c9cf194e86a5b4b.png)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
RTTsum_Cloud
这家伙很懒,什么也没写!
文章
2
回答
0
被采纳
0
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
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
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部