μC/OS-II---消息队列管理2(os_q.c)

news2024/11/27 2:27:50

目录

  • 消息队列的主要优点
  • 消息队列和消息邮箱
  • 消息队列相关操作
    • 向消息队列发送消息(FIFO)
    • 向消息队列发送消息(LIFO)
    • 向消息队列发送消息(扩展)
    • 消息队列获取/无等待
    • 清空消息队列
    • 消息队列信息获取
    • 消息队列中断等待

在这里插入图片描述

消息队列的主要优点

  • 消息队列的主要优点是解耦和异步通信。发送者和接收者之间不需要直接建立连接,它们只需要知道消息队列的名称或标识符即可。发送者将消息发送到队列中后,可以继续执行其他任务,而不需要等待接收者处理消息。接收者可以在合适的时候从队列中获取消息进行处理,这样可以实现异步通信,提高系统的并发性和响应性。
  • 通常会在消息队列中引入消息标识符或者消息类型。发送者在发送消息时,会附带一个标识符或类型,接收者在接收消息时,会根据标识符或类型来判断是否是自己需要处理的消息。这样可以确保每个进程只处理属于自己的消息,避免了拿错信息的问题。
  • 此外,还可以使用互斥锁或其他同步机制来保证在读取和写入消息队列时的原子性操作,避免多个进程同时对消息队列进行读写操作而导致的竞争条件。

消息队列和消息邮箱

  • 消息队列是一个独立的数据结构,多个进程可以共享同一个消息队列,而消息邮箱是与进程关联的,每个进程都有自己的邮箱。此外,消息队列通常是先进先出(FIFO)的,而消息邮箱可以根据实现方式不同具有不同的特性,比如可以是先进先出或者按优先级处理消息。
  • Task也可以设计有“私有”消息队列模式。
  • 总的来说,消息队列更适合实现多个进程之间的解耦和异步通信,而消息邮箱更适合实现单个进程内的消息传递。

消息队列相关操作

向消息队列发送消息(FIFO)

#if OS_Q_POST_EN > 0u
INT8U  OSQPost (OS_EVENT  *pevent,
								void      *pmsg)
{
	OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                       /* Validate 'pevent'                            */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)        /* Validate event block type                    */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	
	if (pevent->OSEventGrp != 0u)                      /* See if any task pending on queue             */
	{
		/* Ready highest priority task waiting on event */
		(void)OS_EventTaskRdy (pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
		OS_EXIT_CRITICAL();
		OS_Sched();                                    /* Find highest priority task ready to run      */
		return (OS_ERR_NONE);
	}
	
	pq = (OS_Q *)pevent->OSEventPtr;                   /* Point to queue control block                 */
	
	if (pq->OSQEntries >= pq->OSQSize)                 /* Make sure queue is not full                  */
	{
		OS_EXIT_CRITICAL();
		return (OS_ERR_Q_FULL);
	}
	
	*pq->OSQIn++ = pmsg;                               /* Insert message into queue                    */
	pq->OSQEntries++;                                  /* Update the nbr of entries in the queue       */
	
	if (pq->OSQIn == pq->OSQEnd)                       /* Wrap IN ptr if we are at end of queue        */
	{
		pq->OSQIn = pq->OSQStart;
	}
	
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

向消息队列发送消息(LIFO)

#if OS_Q_POST_FRONT_EN > 0u
INT8U  OSQPostFront (OS_EVENT  *pevent,
										 void      *pmsg)
{
	OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                      /* Validate 'pevent'                             */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)       /* Validate event block type                     */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	
	if (pevent->OSEventGrp != 0u)                     /* See if any task pending on queue              */
	{
		/* Ready highest priority task waiting on event  */
		(void)OS_EventTaskRdy (pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
		OS_EXIT_CRITICAL();
		OS_Sched();                                   /* Find highest priority task ready to run       */
		return (OS_ERR_NONE);
	}
	
	pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
	
	if (pq->OSQEntries >= pq->OSQSize)                /* Make sure queue is not full                   */
	{
		OS_EXIT_CRITICAL();
		return (OS_ERR_Q_FULL);
	}
	
	if (pq->OSQOut == pq->OSQStart)                   /* Wrap OUT ptr if we are at the 1st queue entry */
	{
		pq->OSQOut = pq->OSQEnd;
	}
	
	pq->OSQOut--;
	*pq->OSQOut = pmsg;                               /* Insert message into queue                     */
	pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

向消息队列发送消息(扩展)

#if OS_Q_POST_OPT_EN > 0u
INT8U  OSQPostOpt (OS_EVENT  *pevent,
									 void      *pmsg,
									 INT8U      opt)
{
	OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                      /* Validate 'pevent'                             */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)       /* Validate event block type                     */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	
	if (pevent->OSEventGrp != 0x00u)                  /* See if any task pending on queue              */
	{
		if ((opt & OS_POST_OPT_BROADCAST) != 0x00u)   /* Do we need to post msg to ALL waiting tasks ? */
		{
			while (pevent->OSEventGrp != 0u)          /* Yes, Post to ALL tasks waiting on queue       */
			{
				(void)OS_EventTaskRdy (pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
			}
		}
		
		else                                          /* No,  Post to HPT waiting on queue             */
		{
			(void)OS_EventTaskRdy (pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
		}
		
		OS_EXIT_CRITICAL();
		
		if ((opt & OS_POST_OPT_NO_SCHED) == 0u)       /* See if scheduler needs to be invoked          */
		{
			OS_Sched();                               /* Find highest priority task ready to run       */
		}
		
		return (OS_ERR_NONE);
	}
	
	pq = (OS_Q *)pevent->OSEventPtr;                  /* Point to queue control block                  */
	
	if (pq->OSQEntries >= pq->OSQSize)                /* Make sure queue is not full                   */
	{
		OS_EXIT_CRITICAL();
		return (OS_ERR_Q_FULL);
	}
	
	if ((opt & OS_POST_OPT_FRONT) != 0x00u)           /* Do we post to the FRONT of the queue?         */
	{
		if (pq->OSQOut == pq->OSQStart)               /* Yes, Post as LIFO, Wrap OUT pointer if we ... */
		{
			pq->OSQOut = pq->OSQEnd;                  /*      ... are at the 1st queue entry           */
		}
		
		pq->OSQOut--;
		*pq->OSQOut = pmsg;                           /*      Insert message into queue                */
	}
	
	else                                              /* No,  Post as FIFO                             */
	{
		*pq->OSQIn++ = pmsg;                          /*      Insert message into queue                */
		
		if (pq->OSQIn == pq->OSQEnd)                  /*      Wrap IN ptr if we are at end of queue    */
		{
			pq->OSQIn = pq->OSQStart;
		}
	}
	
	pq->OSQEntries++;                                 /* Update the nbr of entries in the queue        */
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

消息队列获取/无等待

#if OS_Q_ACCEPT_EN > 0u
void  *OSQAccept (OS_EVENT  *pevent,
									INT8U     *perr)
{
	void      *pmsg;
	OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
	
	if (perr == (INT8U *)0)
	{
		OS_SAFETY_CRITICAL_EXCEPTION();
		return ((void *)0);
	}
	
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                 /* Validate 'pevent'                                  */
	{
		*perr = OS_ERR_PEVENT_NULL;
		return ((void *)0);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)  /* Validate event block type                          */
	{
		*perr = OS_ERR_EVENT_TYPE;
		return ((void *)0);
	}
	
	OS_ENTER_CRITICAL();
	pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
	
	if (pq->OSQEntries > 0u)                     /* See if any messages in the queue                   */
	{
		pmsg = *pq->OSQOut++;                    /* Yes, extract oldest message from the queue         */
		pq->OSQEntries--;                        /* Update the number of entries in the queue          */
		
		if (pq->OSQOut == pq->OSQEnd)            /* Wrap OUT pointer if we are at the end of the queue */
		{
			pq->OSQOut = pq->OSQStart;
		}
		
		*perr = OS_ERR_NONE;
	}
	
	else
	{
		*perr = OS_ERR_Q_EMPTY;
		pmsg  = (void *)0;                       /* Queue is empty                                     */
	}
	
	OS_EXIT_CRITICAL();
	return (pmsg);                               /* Return message received (or NULL)                  */
}
#endif

清空消息队列

#if OS_Q_FLUSH_EN > 0u
INT8U  OSQFlush (OS_EVENT *pevent)
{
	OS_Q      *pq;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                      /* Validate 'pevent'                             */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)       /* Validate event block type                     */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
#endif
	OS_ENTER_CRITICAL();
	pq             = (OS_Q *)pevent->OSEventPtr;      /* Point to queue storage structure              */
	pq->OSQIn      = pq->OSQStart;
	pq->OSQOut     = pq->OSQStart;
	pq->OSQEntries = 0u;
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

消息队列信息获取

#if OS_Q_QUERY_EN > 0u
INT8U  OSQQuery (OS_EVENT  *pevent,
								 OS_Q_DATA *p_q_data)
{
	OS_Q       *pq;
	INT8U       i;
	OS_PRIO    *psrc;
	OS_PRIO    *pdest;
#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
	OS_CPU_SR   cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                       /* Validate 'pevent'                            */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
	if (p_q_data == (OS_Q_DATA *)0)                    /* Validate 'p_q_data'                          */
	{
		return (OS_ERR_PDATA_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)        /* Validate event block type                    */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	p_q_data->OSEventGrp = pevent->OSEventGrp;         /* Copy message queue wait list                 */
	psrc                 = &pevent->OSEventTbl[0];
	pdest                = &p_q_data->OSEventTbl[0];
	
	for (i = 0u; i < OS_EVENT_TBL_SIZE; i++)
	{
		*pdest++ = *psrc++;
	}
	
	pq = (OS_Q *)pevent->OSEventPtr;
	
	if (pq->OSQEntries > 0u)
	{
		p_q_data->OSMsg = *pq->OSQOut;                 /* Get next message to return if available      */
	}
	
	else
	{
		p_q_data->OSMsg = (void *)0;
	}
	
	p_q_data->OSNMsgs = pq->OSQEntries;
	p_q_data->OSQSize = pq->OSQSize;
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

消息队列中断等待

#if OS_Q_PEND_ABORT_EN > 0u
INT8U  OSQPendAbort (OS_EVENT  *pevent,
										 INT8U      opt,
										 INT8U     *perr)
{
	INT8U      nbr_tasks;
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
	
	if (perr == (INT8U *)0)
	{
		OS_SAFETY_CRITICAL_EXCEPTION();
		return (0u);
	}
	
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                           /* Validate 'pevent'                        */
	{
		*perr = OS_ERR_PEVENT_NULL;
		return (0u);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_Q)            /* Validate event block type                */
	{
		*perr = OS_ERR_EVENT_TYPE;
		return (0u);
	}
	
	OS_ENTER_CRITICAL();
	
	if (pevent->OSEventGrp != 0u)                          /* See if any task waiting on queue?        */
	{
		nbr_tasks = 0u;
		
		switch (opt)
		{
			case OS_PEND_OPT_BROADCAST:                    /* Do we need to abort ALL waiting tasks?   */
				while (pevent->OSEventGrp != 0u)          /* Yes, ready ALL tasks waiting on queue    */
				{
					(void)OS_EventTaskRdy (pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
					nbr_tasks++;
				}
				
				break;
				
			case OS_PEND_OPT_NONE:
			default:                                       /* No,  ready HPT       waiting on queue    */
				(void)OS_EventTaskRdy (pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
				nbr_tasks++;
				break;
		}
		
		OS_EXIT_CRITICAL();
		OS_Sched();                                        /* Find HPT ready to run                    */
		*perr = OS_ERR_PEND_ABORT;
		return (nbr_tasks);
	}
	
	OS_EXIT_CRITICAL();
	*perr = OS_ERR_NONE;
	return (0u);                                           /* No tasks waiting on queue                */
}
#endif

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

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

相关文章

rocketmq5.X 单机搭建 虚拟机搭建rocketmq5.1.4 搭建最新版本mq rocketmq5.1.4版本单体搭建 rocketmq(一)

1. 官网下载地址&#xff1a; 下载 | RocketMQ 2. 配置环境&#xff1a; 我是在/etc/profile.d 新建了一个rocketmq_env.sh 配置了jdk, maven, 以及mq. mq文件下载的 配置完之后&#xff0c;刷新环境source /etc/profile 3. 配置rocket mq 的jvm配置&#xff0c;就是两个启…

Docker Compose详细教程(从入门到放弃)

对于现代应用来说&#xff0c;大多都是通过很多的微服务互相协同组成的一个完整应用。例如&#xff0c; 订单管理、用户管理、品类管理、缓存服务、数据库服务等&#xff0c;它们构成了一个电商平台的应 用。而部署和管理大量的服务容器是一件非常繁琐的事情。而 Docker Compos…

基于安卓android微信小程序的装修家装小程序

项目介绍 巧匠家装小程序的设计主要是对系统所要实现的功能进行详细考虑&#xff0c;确定所要实现的功能后进行界面的设计&#xff0c;在这中间还要考虑如何可以更好的将功能及页面进行很好的结合&#xff0c;方便用户可以很容易明了的找到自己所需要的信息&#xff0c;还有系…

PLC电力载波通讯,一种新的IoT通讯技术

前言: PLC-IoT 是 PLC 技术应用在物联场景的创新实践,有效解决电力线路信号干扰、衰减问题,支持 IP 化通信能力,使能终端设备智能化,构建智慧边缘联接。PLC让传统IoT有了更多的连接可能: 电力线通信技术适用的场景包括电力配用电网络、城市智慧路灯、交通路口信号灯、园…

Python代码运行速度提升技巧!Python远比你想象中的快~

文章目录 前言一、使用内置函数二、字符串连接 VS join()三、创建列表和字典的方式四、使用 f-Strings五、使用Comprehensions六、附录- Python中的内置函数总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项…

基于SSM的药店药品销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

IDEA导入jar包

通过maven导入本地包 mvn install:install-file -DfileD:\WebProject\ERP\zhixing-heyue-erp-server\zxhy-service-api\src\main\java\com\zxhy\service\api\invoice\baiwang\lib\com_baiwang_bop_sdk_outer_3_4_393.jar -DgroupIdcom.baiwang -DartifactIdbaiwang.open -Dver…

C语言每日一题(29)合并两个有序链表

力扣网 21合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 思路分析 最基本的一种思路就是&#xff0c;遍历两个链表&#xff0c;将对应结点的值进行比较&#xff0c;题目要求是要升序排…

错误:ERROR:torch.distributed.elastic.multiprocessing.api:failed

在多卡运行时&#xff0c;会出现错误&#xff08;ERROR:torch.distributed.elastic.multiprocessing.api:failed&#xff09;&#xff0c;但是单卡运行并不会报错&#xff0c;通常在反向梯度传播时多卡梯度不同步。但我是在多卡处理数据进行tokenizer阶段报错&#xff0c;这竟然…

ZYNQ实验--Petalinux 安装

一、Petalinux 简介 PetaLinux是一个由Xilinx公司提供的嵌入式Linux开发工具套件&#xff0c;专门用于在Xilinx器件上构建、定制和部署嵌入式Linux系统。这个工具套件旨在简化嵌入式系统的开发过程&#xff0c;特别是针对使用Xilinx的可编程逻辑器件的系统。PetaLinux是Xilinx …

基于SpringBoot的教务管理系统

基于SpringBoot的教务管理系统 教务管理系统开发技术功能模块代码结构运行截图数据库源码获取 教务管理系统 欢迎访问此博客&#xff0c;是否为自己的毕业设计而担忧呢&#xff1f;是否感觉自己的时间不够做毕业设计呢&#xff1f;那你不妨看一下下面的文章&#xff01; 开发…

基于单片机无人售货机仿真及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、商品选择&#xff0c;购买数量选择&#xff0c;投币&#xff0c;液晶1602显示。 3、电机模拟出货。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void lcd_1602_init() //LCD1602初始…

实用干货丨Eolink Apikit 配置和告警规则的各种用法

API在运行过程中可能会遇到各种异常情况&#xff0c;如响应时间过长、调用频率过高、请求参数错误等&#xff0c;这些异常会对系统的稳定性和性能产生严重影响。因此&#xff0c;对API进行异常监控和告警是非常必要的。本文将介绍 Eolink Apikit 中使用的告警规则&#xff0c;帮…

UWA Pipeline 2.5.1 版本更新说明

UWA Pipeline是一款面向游戏开发团队的本地协作平台&#xff0c;旨在为游戏开发团队搭建专属的DevOps研发交付流水线&#xff0c;提供可视化的CICD操作界面、高可用的自动化测试以及UWA性能保障服务的无缝贴合等实用功能。 近期UWA Pipeline迎来2.5.1版本更新&#xff0c;进一…

【小黑送书—第六期】>>AI时代,程序员如何应对挑战——《AI时代系列书籍》

在AI时代&#xff0c;程序员面临着新的机遇和挑战。为了适应这个快速发展的时代&#xff0c;掌握新技能并采取相应的应对策略是至关重要的。 对于办公人员或程序员来说&#xff0c;利用AI可以提高工作效率。例如&#xff0c;使用AI助手可以帮助自动化日常的重复性工作&#xff…

软件测试方案该怎么做?

做某项工作之前都需要有个计划或方案&#xff0c;软件测试亦如此。软件测试方案就是描述测试目的、范围、方法和软件测试的重点等文档。对于验证软件产品的可接受程度编写测试计划文档是一种有用的方式&#xff0c;可以使测试工作和整个开发工作融合起来&#xff0c;让资源和变…

微信公众号会员系统怎么做

一、引言 在这个信息爆炸的时代&#xff0c;微信公众号已经成为了企业和个人品牌的重要宣传阵地。而在公众号运营过程中&#xff0c;会员系统是非常重要的一环。通过建立会员系统&#xff0c;你可以更好地管理粉丝、提升用户黏性&#xff0c;让你的品牌更加强大。本文将为你详…

Golang实现一个一维结构体,根据某个字段排序

package mainimport ("fmt""sort" )type Person struct {Name stringAge int }func main() {// 创建一个一维结构体切片people : []Person{{"Alice", 25},{"Bob", 30},{"Charlie", 20},{"David", 35},{"Eve…

Redis缓存击穿、雪崩、穿透!(超详细)

作者前言: 为了解决Redis的缓存的问提也是在网上找了很多文章来了解,我感觉这篇文章非常好,希望大家了解一下&#xff0c;也是吧这篇文章归类了一下,可以直接在目录中找 缓存的击穿、穿透和雪崩应该是再熟悉不过的词了&#xff0c;也是面试常问的高频试题。 不过&#xff0c;…

用户的生命周期

用户生命周期是指用户在产品使用过程中的状态变化&#xff0c;一般分为5个阶段&#xff0c;分别为引入期、成长期、成熟期、沉默期和流失期。用户生命周期能够反映不同阶段用户的状态&#xff0c;可根据用户的不同状态进行针对性运营。运营中常说的拉新、促活、留存就是基于用户…