RT_Thread内核机制学习(四)队列

队列

队列中每个消息块都有一个头部,指向下一个消息块。
在这里插入图片描述
消息块的内存是连在一起的,但是是用链表组织的。

struct rt_messagequeue
{struct rt_ipc_object parent;                        /**< inherit from ipc_object */void                *msg_pool;                      /**< start address of message queue */rt_uint16_t          msg_size;                      /**< message size of each message */rt_uint16_t          max_msgs;                      /**< max number of messages */rt_uint16_t          entry;                         /**< index of messages in the queue */void                *msg_queue_head;                /**< list head */void                *msg_queue_tail;                /**< list tail */void                *msg_queue_free;                /**< pointer indicated the free node of queue */rt_list_t            suspend_sender_thread;         /**< sender thread suspended on this message queue */
};

共有三个指针,free指向空闲消息链表头部,head指向有数据的第一个消息块,tail指向有消息的最后一个消息块。

创建一个队列,用于线程A、B之间的通信。
队列最多含有5个消息,刚创建时这5个消息都是空的,都放在空闲链表里。
在这里插入图片描述
线程A向队列写入一个本地变量x:从队列的空闲链表中取出一个消息块,把x的值拷贝进去,这时队列中只有一个消息,所以队列的头部、尾部都指向这个消息。

在这里插入图片描述
线程A修改本地变量x为20,并把它写入队列:
从队列的空闲消息链表中取出一个消息,把x的值拷贝进去,放到队列的尾部。
在这里插入图片描述
头指针指向最先写入的消息块,尾写入最后写入的消息块。
在这里插入图片描述
线程B读队列,得到的数据放到本地变量y中,这个数据来自队列头部,链头指针指向下一个。
线程B读出消息后:原来的消息块变为空闲消息块,被放入队列的空闲链表msg_queue_free;

rt_mq_t rt_mq_create(const char *name,rt_size_t   msg_size,rt_size_t   max_msgs,rt_uint8_t  flag)
{struct rt_messagequeue *mq;struct rt_mq_message *head;register rt_base_t temp;RT_DEBUG_NOT_IN_INTERRUPT;/* allocate object */mq = (rt_mq_t)rt_object_allocate(RT_Object_Class_MessageQueue, name);//分配一个消息队列结构体if (mq == RT_NULL)return mq;/* set parent */mq->parent.parent.flag = flag;/* initialize ipc object */rt_ipc_object_init(&(mq->parent));/* initialize message queue *//* get correct message size */mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); //每个消息的size需要对齐mq->max_msgs = max_msgs;/* allocate message pool */mq->msg_pool = RT_KERNEL_MALLOC((mq->msg_size + sizeof(struct rt_mq_message)) * mq->max_msgs); //(每个消息的大小+每个消息结构体的大小)*最大消息数,这是一块连续的内存区域。分配出来的所有消息空间保存在msg_pool中。if (mq->msg_pool == RT_NULL){rt_object_delete(&(mq->parent.parent));return RT_NULL;}/* initialize message list */mq->msg_queue_head = RT_NULL;//头指针和尾指针初始化为空mq->msg_queue_tail = RT_NULL;/* initialize message empty list */mq->msg_queue_free = RT_NULL;for (temp = 0; temp < mq->max_msgs; temp ++) //遍历每一个消息块{head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +temp * (mq->msg_size + sizeof(struct rt_mq_message)));head->next = (struct rt_mq_message *)mq->msg_queue_free;mq->msg_queue_free = head;}/* the initial entry is zero */mq->entry = 0;/* initialize an additional list of sender suspend thread */rt_list_init(&(mq->suspend_sender_thread));return mq;
}
RTM_EXPORT(rt_mq_create);
struct rt_mq_message
{struct rt_mq_message *next;
};//消息结构体

发送消息

/* get a free list, there must be an empty item */msg = (struct rt_mq_message *)mq->msg_queue_free; //从free链表获取一个消息块//取出消息块后,free链表指针指向消息块的下一个
mq->msg_queue_free = msg->next;//将buffer数据拷贝进去
rt_memcpy(msg + 1, buffer, size);//尾部指针指向此消息
mq->msg_queue_tail = msg;//如果头部指针为空,代表第一次存放数据进去,因此头部指针也指向此消息。下一次,消息不为空时,再放消息,头部不变。
if (mq->msg_queue_head == RT_NULL)mq->msg_queue_head = msg;

读入消息

//新的空闲消息块,直接让空闲链表头部指向它,插入表头
msg->next = (struct rt_mq_message *)mq->msg_queue_free;
mq->msg_queue_free = msg;

写消息时的互斥操作

 /* disable interrupt */temp = rt_hw_interrupt_disable();//在取出消息块,写消息之前关中断,其它线程无法打扰。

互斥用关中断来实现。
互斥量也是用关中断实现。

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

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

相关文章

go vet中的那些检测项

go vet 是 Go 语言自带的一个工具&#xff0c;用于分析 Go 代码中的常见错误和潜在问题。它可以检查代码中可能存在的各种问题&#xff0c;例如&#xff1a; 未使用的变量、函数或包 可疑的函数调用 错误的函数签名 程序中的竞态条件 错误的类型转换等 本文意图指令当前go vet所…

在 AWS 中导入 qcow2 镜像

文章目录 在 AWS 中导入 qcow2 镜像使用的格式和问题步骤概述前提条件转换镜像格式并上传至 S3创建角色并配置策略策略文件内容创建container.json配置文件导入镜像创建 AMI 并启动实例参考:在 AWS 中导入 qcow2 镜像 当我们在多云环境中部署应用时,有时候可能需要把基于 qem…

装备一台ubuntu

配置远程连接&#xff1a; ubuntu的root用户无法远程登入问题&#xff1a; openssh安装命令&#xff1a; sudo apt-get install openssh-server 安装完成通过以下命令查看SSH是否启动 ps -e | grep ssh 如果只有ssh-agent表示还没启动&#xff0c;需要&#xff1a; /etc/i…

2023高教社杯数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

Visual Studio软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Visual Studio是微软公司开发的一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于Windows平台上的应用程序和Web应用程序的开发。以下是Visual Studio软件的主要特点和功能&#xff1a; 集成开发环境&#x…

力扣:74. 搜索二维矩阵(Python3)

题目&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返…

Spring与MyBatis集成 AOP整合PageHelper插件

目录 1.什么是集成&#xff1f; 2.Spring与MyBatis集成 3.Spring与MyBatis集成的基本配置 4.AOP整合PageHelper插件 1.什么是集成&#xff1f; 集成是指将不同的组件、框架或系统整合到一起&#xff0c;使它们可以协同工作、相互调用、共享资源等。通过集成&#xff0c;可以…

linux系统(centos、ubuntu、银河麒麟服务、uos、deepin)判断程序是否已安装,通用判断方法:适用所有应用和命令的判断

前言 项目中需要判断linux服务器中是否已经安装了某个服务 方法有很多种&#xff0c;但是很多都不通用&#xff0c; 脚本代码就不容易做成统一的 解决方案 用下面的脚本代码去进行判断 用jdk测试 脚本意思如下&#xff1a; 输入java -version命令&#xff0c;将返回的字…

ES6中promise的使用

ES6中promise的使用 本文目录 ES6中promise的使用基础介绍箭头函数function函数状态 原型方法Promise.prototype.then()Promise.prototype.catch() 静态方法Promise.all()Promise.race()Promise.any() 链式回调 基础介绍 官网&#xff1a;https://promisesaplus.com/ window.…

Tomcat和Servlet基础知识的讲解(JavaEE初阶系列16)

目录 前言&#xff1a; 1.Tomcat 1.1Tomcat是什么 1.2下载安装 2.Servlet 2.1什么是Servlet 2.2使用Servlet来编写一个“hello world” 1.2.1创建项目&#xff08;Maven&#xff09; 1.2.2引入依赖&#xff08;Servlet&#xff09; 1.2.3创建目录&#xff08;webapp&a…

高职教育应对ChatGPT应用的策略

一、完善顶层设计&#xff0c;提升技术水平 在推广ChatGPT平台的过程中&#xff0c;高职院校需要关注技术本身的问题。这就需要在国家和地方政府的引导下&#xff0c;引入更完善的技术顶层设计&#xff0c;提高人工智能在高职教育中的运用水平。具体来说&#xff0c;一方面需要…

linux 设置与命令基础(二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、系统基本操作 二、命令类型 三、命令语法 四、命令补齐 五、命令帮助 六、系统基本操作命令 总结 前言 这是本人学习Linux的第二天&#xff0c;今天主…

高频电流探头的钳口使用和如何调零消磁

高频电流探头采用霍尔效应传感器技术来测量交流和直流信号&#xff0c;标配通用的 BNC 接口&#xff0c;可直接用示波器或记录仪等观察测量波形及数值&#xff0c;具有强大的通用性能。 电流探头钳口使用&#xff1a; 为电流指示方向。测量时&#xff0c;被测导体电流方向与指…

Matlab图像处理-平移运算

几何运算 几何运算又称为几何变换&#xff0c;是将一幅图像中的坐标映射到另外一幅图像中的新坐标位置&#xff0c;它不改变图像的像素值&#xff0c;只是改变像素所在的几何位置&#xff0c;使原始图像按照需要产生位置、形状和大小的变化。 图像几何运算的一般定义为&#…

Day48|leetcode 198.打家劫舍、213.打家劫舍II、打家劫舍|||

leetcode 198.打家劫舍 题目链接&#xff1a;198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 视频链接&#xff1a;动态规划&#xff0c;偷不偷这个房间呢&#xff1f;| LeetCode&#xff1a;198.打家劫舍_哔哩哔哩_bilibili 题目概述 你是一个专业的小偷&#xff0c;…

【微服务】05-网关与BFF(Backend For Frontend)

文章目录 1.打造网关1.1 简介1.2 连接模式1.3 打造网关 2.身份认证与授权2.1 身份认证方案2.1.1 JWT是什么2.1.2 启用JwtBearer身份认证2.1.3 配置身份认证2.1.4 JWT注意事项 1.打造网关 1.1 简介 BFF(Backend For Frontend)负责认证授权&#xff0c;服务聚合&#xff0c;目标…

如何拼接两个视频在一起?

如何拼接两个视频在一起&#xff1f;在度过一个美好周末的时候&#xff0c;我和朋友一起拍摄了两组视频&#xff0c;准备将两个视频合并成一个并发布到朋友圈。这个想法非常棒&#xff0c;但是我在第一步就遇到了麻烦&#xff1a;如何将这两个视频拼接在一起&#xff1f;这听起…

<深度学习基础> 激活函数

为什么需要激活函数&#xff1f;激活函数的作用&#xff1f; 激活函数可以引入非线性因素&#xff0c;可以学习到复杂的任务或函数。如果不使用激活函数&#xff0c;则输出信号仅是一个简单的线性函数。线性函数一个一级多项式&#xff0c;线性方程的复杂度有限&#xff0c;从…

【pyqt5界面化工具开发-8】窗口开发-QDialog对话框

目录 一、调用父类的菜单 二、添加更多的布局在对话框内 一、调用父类的菜单 和前面Qwedget一样的结构&#xff08;不做过多介绍&#xff09; 可以参考代码中的注释 import sys from PyQt5.QtWidgets import QApplication, QPushButton, QDialog# 对话框&#xff08;多运用…

vue中bus的使用和涉及到的问题

创建一个js文件 import Vue from "Vue" export default new Vue 我们可以直接在要使用的页面中引用使用 import bus from /assets/js/eventBus.js;bus.$emit("info", "123") // 使用bus.$on("info", (val) > { // 接收console.l…