Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
源码分析
RT thread 源码分析 —— 线程间通信
发布于 2025-02-23 17:15:13 浏览:14
订阅该版
[tocm] # 邮箱,消息队列 实现邮箱和消息队列的过程与互斥量,信号量实现的思路类似。都需挂起唤醒队列,保护临界数据,实现需求功能,调度时机。 https://club.rt-thread.org/ask/article/3376df70ce39b6bf.html 比较特别是邮箱和消息队列的临界数据还带有一个缓冲区和另一个挂起线程队列 `suspend_sender_thread`。 这个`挂起线程队列里`的线程是等待发送消息的线程。而等待接送消息的线程则在父类成员的挂起线程。 邮箱的缓冲区是一块循环数组。 缓冲区可视化如下:  `input`不变式:缓冲区下一个新邮件的索引。 `output`不变式:缓冲区下一个被输出的邮件的索引。 `entry`不变式:邮件数量 当发送紧急邮件时,紧急邮件将停在output索引,而output指针将会往后移动。 同样是一块内存,消息队列的消息通过链表机制管理,类似于内存池。 缓冲区的初始状态如图所示: 每块消息的消息头都会连接下一个消息的消息头。  而对消息队列多次发送消息,多次接受消息后,一个可能的状态如图所示  `queue`不变式:空闲队列的首元素。 消息队列:先来先出(FIFO)队列。 `head`不变式:消息队列被输出的第一个元素 `tail`不变式:消息队列最后被输出的元素 # 信号 ## 需求明确 RT thread的文档对于信号需求没有太过明确,但有很多特殊情况需要讨论。 场景: 线程A向线程B发送了信号20,但发送一段时间后线程B才取消屏蔽,线程B是否触发信号处理函数? 线程A向线程B发送了多个信号20,多个信号13,线程B如何处理? 线程向处于阻塞状态的线程B发送信号,如何处理线程B? 。。。 根据实现,明确信号在特殊场景的表现: 在接受线程取消屏蔽,接收到多个同类信号时,只会触发一次信号处理函数。 执行信号处理函数期间不会接受其他信号。 接受线程取消屏蔽某类信号后,会处理曾收到过的同类信号,不考虑这个信号收到了多久。 发送信号时,目标线程处于挂起状态时,则直接唤醒。则意味着目标线程的阻塞调用异常,将会返回错误值。 ## 数据结构 本篇先不讲解保存信号信息(siginfo)的代码。 与线程相关的成员: `rt_sigset_t sig_mask; /**< the mask bits of signal */` 不变式:每一位代表一个信号是否屏蔽,若为0,屏蔽,若为1,则接受。 `rt_sigset_t sig_pending;` 不变式:每一位代表一个信号。代表接受过的信号类。若为1,则线程接受过该类信号.为0,则未接受。 `rt_sighandler_t *sig_vectors; /**< vectors of signal handler */` 不变式:指向 [信号服务函数]数组的指针。 接受到信号,需要注册新的服务函数,都需要靠此函数触发,修改对应的服务函数。 `void *sig_ret; /**< the return stack pointer from signal */` 发送信号时, 会在目标线程的栈上初始化一个新的函数帧,是执行信号服务函数的上下文,调度到目标线程时,sp指针跳到此上下文。因此需要临时保存栈指针,执行信号服务函数完后,跳回原来的上下文。 `RT_THREAD_STAT_SIGNAL_PENDING`,`RT_THREAD_STAT_SIGNAL`线程stat与信号相关的状态。 表示线程是否被信号影响,或是否为处理信号的状态。 `static struct rt_spinlock _thread_signal_lock = RT_SPINLOCK_INIT;` 这里不太理解,似乎上锁不是给线程上锁,而是给信号操作上锁。执行信号接口时都必须是单线程执行。 ## 最小可用接口集解读 `rt_signal_unmask,rt_signal_mask`,这里修改目标线程的mask即可。 `rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)` 此函数会调用`rt_thread_alloc_sig`来为向量表分配空间。 再注册向量表中对应的函数。 `rt_thread_kill`是最关键的函数。它依赖两个辅助函数:`_signal_deliver`,`_signal_entry`,`rt_thread_handle_sig`。 `rt_thread_kill`通过`_signal_deliver`来派发信号,`_signal_entry`是初始化函数帧时函数帧的执行入口,最后都通过`rt_thread_handle_sig`遍历已经接受的信号,执行对应的信号服务函数。 ```C++ /* * To deliver a signal to thread, there are cases: * 1. When thread is suspended, function resumes thread and * set signal stat; * 2. When thread is ready: * - If function delivers a signal to self thread, just handle * it. * - If function delivers a signal to another ready thread, OS * should build a slice context to handle it. */ ``` 正如注释所言: `_signal_deliver`会直接唤醒待挂起的线程,若是发送给自己,直接当作函数调用调用即可。 若是其他线程,在目标线程的栈上构建一个执行信号服务函数的上下文。再进行调度。 剩下的便是判断线程状态是否满足必要条件和及时更新线程状态。 值得一提的是schedule似乎掺杂太多,耦合了。就比如这里显然实现`_signal_deliver`的人必须要知道`scheduler`在唤醒线程后,会显式调用信号服务函数,最后再返回schedule。 # 启发 链表和数组的区别:链表应用于内存划分不均匀的场景。链表无法在性能上替代数组,即使是多添加元素,删除元素,少读取元素的场景,因为硬件性能强悍,链表操作的数据很难被缓存,存取地址也更多。 没有一个单独的“内核”存在。进程(线程)上下文为内核上下文和用户上下文。 内核代码只能在进程(线程)上下文或中断上下文被执行。 阻塞线程被信号唤醒后,继续在`scheduler`函数内执行信号服务函数,所以这算在线程上下文内。 整体来看,是多个线程在同时运行。操作系统“躺着”,等待被调用。 # todo - [ ] 以arm架构为例,看看上下文切换的汇编代码 - [ ] 了解信号的siginfo模块
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
catcatbing
这家伙很懒,什么也没写!
文章
8
回答
0
被采纳
0
关注TA
发私信
相关文章
1
kawaii mqtt 严谨使用注意事项,求助
2
关于阅读 device.c 的几点疑惑
3
rt thread studio软件中怎么设置添加pc lint工具
推荐文章
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
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
10
个答案
3
次被采纳
xiaorui
3
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
三世执戟
8
个答案
1
次被采纳
KunYi
8
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
lizimu
2
篇文章
8
次点赞
swet123
1
篇文章
4
次点赞
Days
1
篇文章
4
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部