物联网操作系统学习笔记——消息队列2

本文详细介绍了物联网操作系统中的消息队列实现原理,包括消息队列控制块的组成如头尾指针、任务链表和消息计数,以及消息队列的创建、删除和在任务、中断中的发送与接收过程,强调了并发访问时的同步和保护措施。
摘要由CSDN通过智能技术生成

消息队列实现原理

消息队列控制块
在这里插入图片描述
pcHead和pcTail:队列的头和尾指针。
pcWriteTo和pcReadFrom:队列要入队和出队指向的地址,便于操作
xTasksWaitingToSend、xTasksWaitingToReceive:和任务相关的链表,
uxMessagesWaiting:队列里还没 处理消息的个数
cRxLock\cTxLock:接受锁和发送锁,任务和中断为了防止冲突而定义.

消息队列创建
在这里插入图片描述

//队列实现,实际是xQueueGenericCreate函数传参传入一个队列类型queueQUEUE_TYPE

//队列的创建类型
#define queueQUEUE_TYPE_BASE				( ( uint8_t ) 0U )  //基本类型
#define queueQUEUE_TYPE_SET					( ( uint8_t ) 0U )	//集合类型
#define queueQUEUE_TYPE_MUTEX 				( ( uint8_t ) 1U )	//互斥信号量
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE	( ( uint8_t ) 2U )	//计数信号量
#define queueQUEUE_TYPE_BINARY_SEMAPHORE	( ( uint8_t ) 3U )	//二制信号量
#define queueQUEUE_TYPE_RECURSIVE_MUTEX		( ( uint8_t ) 4U )	//递归信号量


#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
	#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
#endif
	/*
		参数:
			uxItemSize
			uxQueueLength
			ucQueueType
		返回值
			QueueHandle_t   队列的句柄,其实是对于列控制块地址
		
	*/
	QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
	{
   
	Queue_t *pxNewQueue;
	size_t xQueueSizeInBytes;
	uint8_t *pucQueueStorage;


		//队列内存空间为空
		if( uxItemSize == ( UBaseType_t ) 0 )
		{
   
			/* 队列字节大小赋值为0 */
			xQueueSizeInBytes = ( size_t ) 0;
		}
		else
		{
   
			/* 队列字节大小  赋值为  长度*每个队列项的大小 */
			xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
		}
		//申请内存空间  = 消息队列控制块大小+消息队列空间大小
		pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );

		if( pxNewQueue != NULL )
		{
   
			/* 找到消息队列操作空间的首地址 */
			pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );

			//初始化一个新的消息队列
			prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
		}

		return pxNewQueue;
	}


/*
	参数:
		pucQueueStorage:队列操作空间的首地址
		ucQueueType:队列类型
		pxNewQueue :队列句柄
		
*/
static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
{
   
	/* Remove compiler warnings about unused parameters should
	configUSE_TRACE_FACILITY not be set to 1. */
	( void ) ucQueueType;

	if( uxItemSize == ( UBaseType_t ) 0 )
	{
   
		/* 把队列控制块首地址赋值到队列头指针上  ????  这是互斥信号使用,后面再分析 */
		pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;
	}
	else
	{
   
		/* 把队列空间首地址赋值给队列头指针上 */
		pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;
	}

	/* 长度 单元大小 */
	pxNewQueue->uxLength = uxQueueLength;
	pxNewQueue->uxItemSize = uxItemSize;
	//队列重置函数
	( void ) xQueueGenericReset( pxNewQueue, pdTRUE );


}
/*
	参数:
		xQueue  队列句柄 
		xNewQueue  操作队列的状态是什么,新建pdTURE还是已经创建好了
	返回值:
		

*/
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
{
   
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
	//进入临界段,这个时候操作队列控制块,不允许打断
	taskENTER_CRITICAL();
	{
   
	/*	
		1、头地址赋值
		2、等待处理的消息个数为0
		3、写入指针赋值为队列头指针
		4、读出指针写入最后一个可用消息
		5、赋值队列为解锁状态
	*/
		pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
		pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;
		pxQueue->pcWriteTo = pxQueue->pcHead;
		pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );
		pxQueue->cRxLock = queueUNLOCKED;
		pxQueue->cTxLock = queueUNLOCKED;
		//判断是否为新建队列
		if( xNewQueue == pdFALSE )
		{
   
			/* 判断发送等待列表里面是否有任务 */
			if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值