RT-Thread 线程间通信

线程间通信

在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取,根据读取到的全局变量值执行相应的动作,达到通信协作的目的。

邮箱

邮箱服务是实时操作系统中一种典型的线程间通信方法。
有两个线程,线程1检测按键状态并发送,线程2读取按键的状态相应地改变LED的亮灭。
这里就可以使用邮箱的方式进行通信,线程1将按键的状态作为邮件发送到邮箱,线程2在邮箱中读取邮件获得按键状态并对LED执行亮灭操作。

邮箱的工作机制

RT-Thread操作系统的邮箱用于线程间通信,特点是开销比较低,效率较高。邮箱中的每一封邮件只能容纳固定的4字节内容(针对32位处理系统,指针的大小即为4个字节,所以一封邮件恰好能够容纳一个指针)。典型的邮箱也称作交换消息,如下图所示,线程或中断服务例程把一封4字节长度的邮件发送到邮箱中,而一个或多个线程可以从邮箱中接收这些邮件并进行处理。
在这里插入图片描述
非阻塞方式的邮件发送过程能够安全的应用于中断服务中,是线程、中断服务、定时器向线程发送消息的有效手段。
通常来说,邮件收取过程可能是阻塞的,这取决于邮箱中是否有邮件,以及收取邮件时设置的超时时间。当邮箱中不存在邮件且超时时间不为 0 时,邮件收取过程将变成阻塞方式。在这类情况下,只能由线程进行邮件的收取。

当一个线程向邮箱发送邮件时,如果邮箱没满,将把邮件复制到邮箱中。如果邮箱已经满了,发送线程可以设置超时时间,选择等待挂起或直接返回 - RT_EFULL。如果发送线程选择挂起等待,那么当邮箱中的邮件被收取而空出空间来时,等待挂起的发送线程将被唤醒继续发送。

当一个线程从邮箱中接收邮件时,如果邮箱是空的,接收线程可以选择是否等待挂起直到收到新的邮件而唤醒,或可以设置超时时间。当达到设置的超时时间,邮箱依然未收到邮件时,这个选择超时等待的线程将被唤醒并返回 - RT_ETIMEOUT。如果邮箱中存在邮件,那么接收线程将复制邮箱中的 4 个字节邮件到接收缓存中。

邮箱控制块

在RT-Thread中,邮箱控制块是操作系统用于管理邮箱的一个数据结构,由结构体struct rt_mailbox表示。

struct rt_mailbox
{struct rt_ipc_object parent;rt_uint32_t* msg_pool;rt_uint16_t size;rt_uint16_t entry;rt_uint16_t in_offset,out_offset;rt_list_t suspend_sender_thread; 
}

创建和删除邮箱

rt_mailbox_t rt_mb_create(const char* name, rt_size_t size, rt_uint8_t flag);

创建邮箱对象时会先从对象管理器中分配一个邮箱对象,然后给邮箱动态分配一块内存空间用来存放邮件,这块内存的大小等于邮件大小与邮箱容量的乘积,接着初始化接收邮件数目和发送邮件在邮箱中的偏移量。

发送邮件

线程或中断服务程序可以通过邮箱给其他线程发送邮件,发送邮件函数接口如下:

rt_err_t rt_mb_send(rt_mailbox_t mb, rt_uint32_t value);

发送的邮件可以是 32 位任意格式的数据,一个整型值或者一个指向缓冲区的指针。当邮箱中的邮件已经满时,发送邮件的线程或者中断程序会收到 -RT_EFULL 的返回值。

邮箱的使用场合

邮箱是一种简单的线程间消息传递方式,特点是开销比较低,效率较高。
能够一次传递一个4字节大小的邮件,并且邮箱具备一定的存储功能,能够缓存一定数量的邮件数(邮件数由创建、初始化邮箱时指定的容量决定)。
邮箱中一封邮件的最大长度是4字节,所以邮箱能够用于不超过4字节的消息传递。
由于在32位系统上,4字节的内容恰好可以放置一个指针,因此当需要再线程间传递比较大的信息时,可以把指向一个缓冲区的指针作为邮件发送到邮箱中。

struct msg
{rt_uint8_t *data_ptr;rt_uint32_t data_size;
}

对于这样一个消息结构体,其中包含了指向数据的指针data_ptr和数据块长度的变量data_size。

消息队列

消息队列是另一种常用的线程间通讯方式,是邮箱的扩展。
可以应用在多种场合:线程间的消息交换、使用串口接收不定长数据等。

消息队列的工作机制

消息队列能够接收来自线程或中断服务例程中不固定长度的消息,并把消息缓存在自己的内存空间中。其它消息也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。
当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。消息队列是一种异步的通信方式。

如下图所示,线程或中断服务例程可以将一条或多条消息放入消息队列中。同样,一个或多个线程也可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常将先进入消息队列的消息先传给线程,也就是说,线程先得到的是最先进入消息队列的消息,即先进先出原则(FIFO)。
在这里插入图片描述
RT-Thread操作系统的消息队列对象由多个元素组成,当消息队列被创建时,它就被分配了消息队列控制块:消息队列名称、内存缓冲区、消息大小以及队列长度等。
同时每个消息队列对象中包含着多个消息框,每个消息框可以存放一条消息;消息队列中的第一个和最后一个消息框被分别称为消息链表头和消息链表尾,对应于消息队列控制块中的msg_queue_head和msg_queue_tail;有些消息框可能是空的,它们可能通过msg_queue_free形成一个空闲消息框链表。
所有消息队列中的消息框总数即是消息队列的长度,这个长度可在消息队列创建时指定。

消息队列控制块

struct rt_messagequeue
{struct rt_ipc_object parent;void* msg_pool;//指向存放消息的缓冲区的指针rt_uint16_t msg_size;rt_uint16_t max_msgs;rt_uint16_t entry;void* msg_queue_head;               /* 消息链表头 */void* msg_queue_tail;               /* 消息链表尾 */void* msg_queue_free;               /* 空闲消息链表 */rt_list_t suspend_sender_thread;    /* 发送线程的挂起等待队列 */
}

发送消息

线程或中断服务程序都可以给消息队列发送消息。
当发送消息时,消息队列对象先从空闲消息链表上取下一个空闲消息块,把线程或者中断服务程序发送的消息内容复制到消息块上,然后把该消息块挂到消息队列的尾部。
当且仅当空闲消息链表上有可用的空闲消息块时,发送者才能成功发送消息;当空闲消息链表上无可用消息块,说明消息队列已满,此时,发送消息的的线程或者中断程序会收到一个错误码(-RT_EFULL)。发送消息的函数接口如下:

发送消息时,发送至需指定发送的消息队列的对象句柄(即指向消息队列控制块的指针),并且指定发送的消息内容以及消息大小。
在发送一个普通消息之后,空闲消息链表上的队首消息被转移到了消息队列尾。

消息队列的使用场合

消息队列可以应用于发送不定长消息的场合,包括线程与线程间的消息交换,以及中断服务例程中给线程发送消息(中断服务例程不能接收消息)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/614130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity中向量的点乘、叉乘区别和作用以及经典案例

文章目录 点乘(Dot Product)叉乘(Cross Product)向量归一化(Normalize)其他作用 unity开发中我们要计算角度,判断位置,常用点乘、叉乘、归一化等等,我们看看他们的使用案…

Flashduty 案例分享 - 途游游戏

Flashduty 作为功能完备的事件OnCall中心,可以接入云上、云下不同监控系统,统一做告警降噪分派、认领升级、排班协同,已经得到众多先进企业的认可。我们采访了一些典型客户代表,了解他们的痛点、选型考虑和未来展望,集…

JavaScript复习小案例

JavaScript实现简易留言板 效果图 完整代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>留言板</title><style>body {background-color: #f4f4f4;}/* 外部容器样式设置 */.wrapper {width: 400px;heigh…

建造者模式深入理解:演示建造单个和多个产品的实践,结合模板模式;支持并行构建,通俗易懂

首先呢看下建造者的定义是什么样的&#xff0c;先读一遍 建造者模式 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它主要用于将一个复杂对象的构建过程与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表现形式。这种模式…

微软Office 2019 批量授权版

软件介绍 微软办公软件套件Microsoft Office 2019 专业增强版2024年1月批量许可版更新推送&#xff01;Office2019正式版2018年10月份推出&#xff0c;主要为多人跨平台办公与团队协作打造。Office2019整合对过去三年在Office365里所有功能&#xff0c;包括对Word、Excel、Pow…

【PyQt小知识 - 7】:QLineEdit设置输入的文本以圆点或星号等方式显示

文章目录 setEchoMode setEchoMode 在PyQt中&#xff0c;QLineEdit是一种用于接收用户输入的小部件&#xff08;widget&#xff09;。setEchoMode是QLineEdit类中的一个方法&#xff0c;可以用于设置文本输入框中的文本显示模式。它接受一个参数来指定要使用的模式。 setEcho…

GEE查看MODIS的NDVI、EVI产品并生成逐日/逐月NDVI曲线

目录 MOD13Q1MOD09GA计算逐日/逐月NDVI生成曲线参考博文 MOD13Q1 MOD13Q1有两个产品&#xff1a;NDVI和EVI&#xff0c;每16天为全球提供&#xff0c;分辨率为250M 通过查看时间&#xff0c;该NDVI产品是16天一景 MOD09GA 提供逐日的表面反射率产品&#xff0c;分辨率为500m…

09Bean的生命周期/作用域不同管理方式不同/自己new的对象纳入Spring容器管理

Spring其实就是一个管理Bean对象的工厂。它负责对象的创建&#xff0c;对象的销毁等。 所谓的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程。 Bean的生命周期之5步 ● 第一步&#xff1a;实例化Bean(无参构造方法执行) ● 第二步&#xff1a;Bean属性赋值(注…

一文搞懂MongoDB

简介 什么是MongoDB MongoDB是一个基于分布式文件存储的NoSQL数据库&#xff0c;基于C语言开发而成的。它以文档存储格式&#xff08;BSON&#xff09;为基础&#xff0c;是由字段和值对组成的数据结构。 扩展&#xff1a; BSON&#xff08;Binary JSON&#xff09;是一种二进…

力扣日记1.11-【二叉树篇】450. 删除二叉搜索树中的节点

力扣日记&#xff1a;【二叉树篇】450. 删除二叉搜索树中的节点 日期&#xff1a;2024.1.11 参考&#xff1a;代码随想录、力扣 450. 删除二叉搜索树中的节点 题目描述 难度&#xff1a;中等 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key…

区间预测 | Matlab实现CNN-BiLSTM-KDE的卷积双向长短期神经网络结合核密度估计多变量时序区间预测

区间预测 | Matlab实现CNN-BiLSTM-KDE的卷积双向长短期神经网络结合核密度估计多变量时序区间预测 目录 区间预测 | Matlab实现CNN-BiLSTM-KDE的卷积双向长短期神经网络结合核密度估计多变量时序区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CNN-BiLSTM-KDE多…

【python】python新年烟花代码【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 新年的钟声即将敲响&#xff0c;为了庆祝这个喜庆的时刻&#xff0c;我们可以用 Python 编写一个炫彩夺目的烟花盛典。本文将详细介绍如何使用 Pygame 库创建一个令人惊叹的烟花效果。 一、效果图&#xff1a; 二…

安防视频监控系统EasyCVR设备分组中在线/离线数量统计的开发与实现

安防视频监控EasyCVR系统具备较强的兼容性&#xff0c;它可以支持国标GB28181、RTSP/Onvif、RTMP&#xff0c;以及厂家的私有协议与SDK&#xff0c;如&#xff1a;海康ehome、海康sdk、大华sdk、宇视sdk、华为sdk、萤石云sdk、乐橙sdk等。EasyCVR平台可覆盖多类型的设备接入&am…

R语言下载安装及VScode配置

文章目录 1. R 下载和安装1.1 下载1.2 安装 2. VSCODE 配置2.1 安装R拓展2.2 安装R语言辅助功能包2.3 DEBUG 1. R 下载和安装 1.1 下载 网址&#xff1a;https://www.r-project.org/ 选择一个镜像地址下载 选择对应的版本 一般选择base即可 1.2 安装 下载安装包后按提示安装…

jupyter notebook 配置conda 虚拟环境python

conda创建python环境 conda create -n openvoice python3.9 激活环境 source activate openvoice 在虚拟环境中安装ipykernel pip install ipykernel 添加虚拟环境进到 jupyter notebook python -m ipykernel install --user --name openvoice --display-name openvoice …

Springboot+vue的毕业论文管理系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的毕业论文管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的毕业论文管理系统&#xff0c;采用M&#xff08;model&…

QT延时五种实现方法

QT中没有提供专用延时函数&#xff0c;但有多种实现方法&#xff0c;各有特点&#xff0c;如下所示&#xff1a; 一.阻塞方式 1.多线程程序使用QThread::sleep()或者QThread::msleep()或QThread::usleep()或QThread::wait()进行延时处理。 Sleep不会释放对象锁&#xff0c;其…

第3章:python的判断语句

学一门语言&#xff0c;无外乎多敲&#xff0c;多用&#xff0c;记得回顾昨天写过的代码呀 布尔类型和比较运算符 布尔类型的定义 使用比较运算符进行比较运算得到布尔类型的结果 比较运算符 """ 演示布尔类型的定义 以及比较运算符的应用 ​ """…

并发前置知识一:线程基础

一、通用的线程生命周期&#xff1a;“五态模型” 二、java线程有哪几种状态&#xff1f; New&#xff1a;创建完线程Runable&#xff1a;start(),这里的Runnable包含操作的系统的Running&#xff08;运行状态&#xff09;和Ready&#xff08;上面的可运行状态&#xff09;Blo…

vscode配置Todo Tree插件

一、在VSCode中安装插件Todo Tree ​​​​ 二、按下快捷键ctrlshiftP&#xff0c;输入setting.jspn 选择相应的配置范围&#xff0c;我们选择的是用户配置 Open User Settings(JSON)&#xff0c;将以下代码插入其中。 {//todo-tree 标签配置从这里开始 标签兼容大小写字母(…