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

目录

  • 消息队列的主要优点
  • 消息队列和消息邮箱
  • 消息队列相关操作
    • 向消息队列发送消息(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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx启动命令

普通启动 切换到nginx安装目录的sbin目录下&#xff0c;执行&#xff1a;./nginx 通过配置文件启动 ./nginx -c /usr/local/nginx/conf/nginx.conf /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 其中-c是指定配置文件,而且配置文件路径必须指定绝对路…

YOLO改进系列之注意力机制(CoordAttention模型介绍)

简介 在轻量级网络上的研究表明&#xff0c;通道注意力会给模型带来比较显著的性能提升&#xff0c;但是通道注意力通常会忽略对生成空间选择性注意力图非常重要的位置信息。因此&#xff0c;新加坡国立大学的提出了一种为轻量级网络设计的新的注意力机制&#xff0c;该机制将…

RabbitMQ之死信队列

文章目录 一、死信的概念二、死信的来源三、实战1、消息 TTL 过期2、队列达到最大长度3、消息被拒 总结 一、死信的概念 先从概念解释上搞清楚这个定义&#xff0c;死信&#xff0c;顾名思义就是无法被消费的消息&#xff0c;字面意思可以这样理解&#xff0c;一般来说&#x…

转载:YOLOv8改进全新Inner-IoU损失函数:扩展到其他SIoU、CIoU等主流损失函数,带辅助边界框的损失

0、摘要 随着检测器的快速发展&#xff0c;边界框回归&#xff08;BBR&#xff09;损失函数不断进行更新和优化。然而&#xff0c;现有的 IoU 基于 BBR 仍然集中在通过添加新损失项来加速收敛&#xff0c;忽略了 IoU 损失项本身的局限性。尽管从理论上讲&#xff0c;IoU 损失可…

Android10 手势导航

种类 Android10 默认的系统导航有三种&#xff1a; 1.两个按钮的 2.三个按钮的 3.手势 它们分别对应三个包名 frameworks/base/packages/overlays/NavigationBarMode2ButtonOverlay frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay frameworks/base/packa…

怎么恢复删除的数据? 8个有效的数据恢复方法

无论您在保存备份方面多么小心&#xff0c;灾难有时还是会发生。有时您的备份软件无法按预期运行。 如果您的外部驱动器靠近您的设备&#xff0c;发生火灾/洪水/故障时&#xff0c;有时备份会与原始文件一起丢失。即使是云存储也不能避免故障。 还有一个事实是&#xff0c;我…

C#检查服务状态,以及进行服务启停

1. linux环境 linux环境通过执行bash命令直接执行&#xff1a; public string RunCmdLinux(string cmd){var proc new Process();System.Console.Write($"Run Linux cmd > [{cmd}] START!");proc.StartInfo.CreateNoWindow true;proc.StartInfo.FileName &…

TOUGH系列软件教程

查看原文>>>全流程TOUGH系列软件实践技术应用 TOUGH系列软件是由美国劳伦斯伯克利实验室开发的&#xff0c;旨在解决非饱和带中地下水、热运移的通用模拟软件。和传统地下水模拟软件Feflow和Modflow不同&#xff0c;TOUGH系列软件采用模块化设计和有限积分差网格剖分…

『C++成长记』C++入门——内联函数

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、内联函数 &#x1f4d2;1.1内联函数的概念 &#x1f4d2;1.2内联函数的特征 …

js中的instance,isPrototype和getPrototypeOf的使用,来判断类的关系

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…

网络类型及数据链路层的协议

网络类型 --- 根据数据链路层使用的协议来进行划分的。 MA网络 --- 多点接入网络 BMA --- 广播型多点接入网络---以太网协议 NBMA --- 非广播型多点接入网络 以太网协议 --- 需要使用mac地址对不同的主机设备进行区分和标识 --- 以太网之所以需要使用mac地址进行数据寻址&…

基于SSM的校园停车场管理系统设计与实现

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

Adobe Illustrator——原创设计的宝藏软件

今天&#xff0c;我们来谈谈一款在Adobe系列中曾经多次给大家都提到的原创性极强的设计理念丰富的矢量图形编辑软件——Adobe Illustrator。 Adobe Illustrator&#xff0c;其定位是一款与Photoshop相类似对矢量图形进行编辑的软件。 Adobe Illustrator&#xff0c;作为全球最著…

未来10年,NAND 与DRAM依然是存储主角

根据Yole Group调查机构的数据显示&#xff0c;在2022年独立记忆体&#xff08;Stand-alone Memory&#xff09;整体市场达到了1440亿美元。其中DRAM占比55.4%&#xff0c;NAND占比40.8%。剩下的NOR、(NV)SRAM/FRAM、EEPROM、新型非易失存储(PCM, ReRAM and STT-MRAM)等占比3.8…

2023.11.14 关于 Spring Boot 创建和使用

目录 Spring Boot Spring Boot 项目的创建 网页版创建 Spring Boot 项目 Spring Boot 目录说明 项目运行 Spring Boot Spring Boot 是基于 Spring 设计的一个全新的框架&#xff0c;其目的是用来简化 Spring 的应用、初始搭建、开发的整个过程Spring Boot 就是一个整合了…

C语言入门这一篇就够了(入门篇2)

接上篇C语言入门这一篇就够了&#xff08;入门篇1&#xff09; 今天主要讲解基本语法&#xff0c;话不多说&#xff0c;直接上干货。 C语言语法有哪些 数据类型&#xff1a;C语言有多种数据类型&#xff0c;包括整数类型&#xff08;如 int、long&#xff09;、浮点类型&#x…

移动机器人路径规划(二)--- 图搜索基础,Dijkstra,A*,JPS

目录 1 图搜索基础 1.1 机器人规划的配置空间 Configuration Space 1.2 图搜索算法的基本概念 1.3 启发式的搜索算法 Heuristic search 2 A* Dijkstra算法 2.1 Dijkstra算法 2.2 A*&&Weighted A*算法 2.3 A* 算法的工程实践中的应用 3 JPS 1 图搜索基础 1.1…

Mysql中的JDBC编程

JDBC编程 1.JDBC的数据库编程2.JDBC工作原理3.JDBC使用3.1JDBC开发案例3.2JDBC使用步骤总结 4.JDBC API4.1数据库连接Connection4.2 Statement对象4.3 ResultSet对象4.4 释放 5.Java代码操作数据库 1.JDBC的数据库编程 JDBC&#xff0c;即Java Database Connectivity&#xff0…

20 - 欲知JVM调优先了解JVM内存模型

从今天开始&#xff0c;我将和你一起探讨 Java 虚拟机&#xff08;JVM&#xff09;的性能调优。JVM 算是面试中的高频问题了&#xff0c;通常情况下总会有人问到&#xff1a;请你讲解下 JVM 的内存模型&#xff0c;JVM 的性能调优做过吗&#xff1f; 1、为什么 JVM 在 Java 中…

springboot--单元测试

单元测试 前言1、写测试要用的类2、写测试要用的类3、运行测试类4、spring-boot-starter-test默认提供了以下库4.1 junit54.1.1 DisplayName:为测试类或者测试方法设置展示名称4.1.2 BeforeAll&#xff1a;所有测试方法运行之前先运行这个4.1.3 BeforeEach&#xff1a;每个测试…