Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
bug
互斥锁mutex互斥量
优先级
【讨论】关于v4.0.4版本中解决的使用互斥量导致优先级反转的问题探讨
发布于 2021-10-21 22:39:03 浏览:2366
订阅该版
[tocm] # 关于RT-Thread v4.0.4 版本中解决的使用互斥量导致优先级反转的问题探讨 > 昨天晚上(2021.10.20),rtt 组织了一场线上发布会,展示了 v4.0.4 版本的一些新特性,以及修复的一些问题。其中,@满鉴霆 老师演讲中讲述的一个关于使用互斥量导致线程优先级反转问题,很有意思。 ## 一、简单介绍互斥量 互斥量是线程间同步的一种方式,又叫相互排斥的信号量,是一种特殊的二值信号量。互斥量类似于只有一个车位的停车场:当有一辆车进入的时候,将停车场大门锁住,其他车辆在外面等候。当里面的车出来时,将停车场大门打开,下一辆车才可以进入。(引用自 RTT 文档) ## 二、互斥量解决了什么问题 ### 2.1 线程优先级反转问题 假设当前有三条线程,分别是 A、B、C,它们的优先级关系是 A > B > C,以及一个公用的内存空间 M。为了保证内存空间内数据的安全性,同一时间段内不能有超过一条线程进行操作。即当 C 正在读取 M 的数据时,A 或 B 不能对 M 做修改。 由于这样的规定,会造成优先级反转问题: ![61fa16d75610ca418c881a704571fa29.jpg.webp](https://oss-club.rt-thread.org/uploads/20211021/61fa16d75610ca418c881a704571fa29.jpg.webp) 1. C 就绪,并获得了 M 的控制权 2. A 就绪,优先级比 C 高,CPU 优先处理 A 3. A 尝试获取 M 的控制权,因为 C 正在持有 M 的控制权,因此挂起等待;C 继续读取 M 4. B 就绪,优先级比 C 高,CPU 优先处理 B 5. B 任务执行完成并挂起,C 继续读取 M 6. C 完成了读取 M 数据的操作,释放了 M 的控制权,轮到 A 对 M 进行修改 通过上面的流程,很明显,我们发现,虽然线程 B 的优先级比线程 A 低,但是却优先执行了,这不符合我们对系统实时性的要求。 ### 2.2 互斥量的解决方法 互斥量使用优先级继承协议,解决了上述的优先级反转问题: ![ad862ca851af7f05406b3d88d230b11a.jpg.webp](https://oss-club.rt-thread.org/uploads/20211021/ad862ca851af7f05406b3d88d230b11a.jpg.webp) 1. C 就绪,并获得了 M 的控制权 2. A 就绪,优先级比 C 高,CPU 优先处理 A 3. A 尝试获取 M 的控制权,因为 C 正在持有 M 的控制权,因此挂起等待;依据优先级继承协议,线程 C 的优先级被提升到与 A 相等,即此时线程优先级关系是:A = C > B;C 继续读取 M 4. C 完成了读取 M 数据的操作,释放了 M 的控制权,优先级被恢复原样,轮到 A 对 M 进行修改,唤醒 A 5. A 任务执行完成并挂起;B 在3-4之间已就绪,当时因优先级比 C 低,所以无法得到执行,而此时优先级比 C 高,CPU 优先唤醒处理 B 6. B 任务执行完成并挂起,C 继续完成任务 ## 三、互斥量制造了什么问题 ### 3.1 错误地使用了 FIFO flag 当用户需要避免上述线程优先级反转问题时,就需要用到互斥量对线程做同步。互斥量由 IPC 容器管理,因此线程想要获取互斥量时,需要在 IPC 中排队等待。IPC 的排队方式有两种: - RT_IPC_FLAG_FIFO:先进先出,队列按照先进先出方式排队 - RT_IPC_FLAG_PRIO:优先级等待,队列将按照优先级进行排队,优先级高的等待线程将会插队排在优先级低的等待线程前 FIFO 属于非实时调度方式,所有排队等待的线程不再具有优先级的特性。然而,在创建/初始化(create/init)互斥量时,函数却允许用户使用 RT_IPC_FLAG_FIFO 参数,这会导致如下情形: ![2832d07e4bdede3e851bb696ecd73a44.jpg.webp](https://oss-club.rt-thread.org/uploads/20211021/2832d07e4bdede3e851bb696ecd73a44.jpg.webp) 1. C 就绪,并获得了 M 的控制权 2. B 就绪,优先级比 C 高,CPU 优先处理 B 3. B 尝试获取 M 的控制权,因为 C 正在持有 M 的控制权,因此挂起等待;依据优先级继承协议,线程 C 的优先级被提升到与 B 相等,即此时线程优先级关系是:A > B = C,B 进入 FIFO 队列,并排在第一位;C 继续读取 M 4. A 就绪,优先级比 C 高,CPU 优先处理 A 5. A 尝试获取 M 的控制权,因为 C 正在持有 M 的控制权,因此挂起等待;依据优先级继承协议,线程 C 的优先级被提升到与 A 相等,即此时线程优先级关系是:A = C > B,A 进入 FIFO 队列,根据先进先出原则,排在第二位,B 后面;C 继续读取 M 6. C 完成了读取 M 数据的操作,释放了 M 的控制权,优先级被恢复原样,根据 FIFO 队列,轮到 B 持有 M 的控制权,唤醒 B 7. B 完成了读取 M 数据的操作,释放了 M 的控制权,优先级被恢复原样,根据 FIFO 队列,轮到 A 持有 M 的控制权,唤醒 A 8. A 任务执行完成并挂起,B 继续任务 9. B 任务执行完成并挂起,C 继续任务 由此我们发现,虽然 A 优先级比 B 高,但是由于 B 比 A 先进入 FIFO 队列,导致 B 比 A 优先得到 M 的控制权,并优先执行,这不符合我们使用互斥量的目的。 同时,由于 A 挂起等待互斥量,因此 B 释放互斥量之前,A 都不会被唤醒(除非超时)。这会使得其他优先级高于 B,低于 A 的线程都会优先于 A 执行。谁能忍? ### 3.2 正确的使用方式 新版本已修复以上出现的优先级反转问题,在创建/初始化(create/init)互斥量时,忽略用户给出的排队方式(flag),只使用 RT_IPC_FLAG_PRIO。 ![c5a35e5cef2d41d0e65ff629fc33f257.jpg.webp](https://oss-club.rt-thread.org/uploads/20211022/c5a35e5cef2d41d0e65ff629fc33f257.jpg.webp) ## 四、总结 互斥量的诞生就是为了解决优先级反转的问题,但是错误地使用互斥量反而会让情况变得更糟糕。同时,这个 bug 相对隐蔽,不易被察觉,初学者(比如我)容易错误地使用,调试时也不容易复现。因此,修复此 bug 是很重要的。 ## 五、结尾 感谢 RTT 昨晚组织的特性解读会,的抽奖活动,让我终于中了一次奖哈哈哈!虽然是三等奖一条数据线,但这是我用这个抽奖小程序以来第一次中奖,真的很想吐槽那个抽奖小程序…… 另外,解读会有回放(虽然我暂时不知道在哪)。
16
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
杰阿阿杰
这家伙很懒,什么也没写!
文章
2
回答
2
被采纳
0
关注TA
发私信
相关文章
1
M5311出现AT response get line failed!
2
可否将LWIP升级到2.1.2 和 2.0.3?
3
signal内核是不是有问题,还是我方法不对
4
关于在stm32F107CVT6中使用以太网芯片DM9161AEP的内存不足异常
5
4.0.1版本的看门狗是不是有bug?
6
workqueue中调用rt_i2c_transfer互斥锁线程bug
7
DMA 串口7 严重BUF反馈
8
rt_event_recv bug
9
小内存管理法里面heap_mem 初始化问题
10
kawaii_mqtt AT使用长时间运行死机的原因分析
推荐文章
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
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部