【RTOS】RTOS源码基础之队列结构体


前言

以下 RTOS 是基于 FreeRTOS 源码分析。
建议直接看源码去了解。

李柱明博客:https://www.cnblogs.com/lizhuming/p/15487239.html

IPC

本人认为在学习 RTOS 任务间通信时必须了解的一个结构体就是 struct QueueDefinition,其源码参考 附件-源码。
该结构体被运用到消息队列、二进制信号量、计数信号量、互斥量和递归互斥量等等关于任务间通信的控件。

这些控件在系统中都是由 控制块 + 存储区 组成,而该结构体就是控制块的角色,管理其对应的存储区。

成员剖析

在成员剖析时默认按消息队列的作用去剖析。

int8_t *pcHead;:

/* 该队列存储区的起始位置,对应第一个消息空间。*/
int8_t *pcHead;

int8_t *pcTail;:

/* 消息队列存储区的结尾位置。
 * 结合 pcHead 指针就是整个存储区合法区域。*/
int8_t *pcHead;

int8_t *pcWriteTo;:

/* 写指针,指向存储区中下一个空闲的空间。
 * 队列下次写数据的位置,需要入队时调用该指针写入数据。*/
int8_t *pcWriteTo;

int8_t *pcReadFrom;:

/* 读指针,指向存储区中下一个有效数据的空间。
 * 队列下次读取数据的位置,需要出队时调用该指针写入数据。*/
int8_t *pcReadFrom;

UBaseType_t uxRecursiveCallCount;:

/* 递归次数。
 * 用于互斥量时使用,与 pcReadFrom 为联合体。
 * 记录递归互斥量被调用的次数。 */
UBaseType_t uxRecursiveCallCount;

List_t xTasksWaitingToSend;:

/* 等待发送的任务列表。
 * 当队列存储区满时,需要发送消息的任务阻塞时记录到该链表。
 * 按任务优先级排序。 */
List_t xTasksWaitingToSend;

List_t xTasksWaitingToReceive;:

/* 等待接收的任务列表。
 * 当队列存储区为空时,需要获取消息的任务阻塞时记录到该链表。
 * 按任务优先级排序。 */
List_t xTasksWaitingToReceive;

volatile UBaseType_t uxMessagesWaiting;:

/* 当前消息节点的个数。
 * 即是当前有效消息数量。
 * 二值信号量、互斥信号量时:表示有无信号量可用。
 * 计数信号量时:有效信号量个数。 */
volatile UBaseType_t uxMessagesWaiting;

UBaseType_t uxLength;:

/* 当前队列最大节点总数。
 * 即是最多能存放多少个消息。
 * 二值信号量、互斥信号量时:最大为1。
 * 计数信号量时:最大的信号量个数。 */
UBaseType_t uxLength;

UBaseType_t uxItemSize;:

/* 单个节点的大小。
 * 单个消息的大小。
 * 二值信号量、互斥信号量时:0。
 * 计数信号量时:0。 */
UBaseType_t uxItemSize;

volatile int8_t cRxLock;:

/* 记录出队的数据项个数。
 * 即是需要解除多少个阻塞在接收等待列表中的任务。 */
volatile int8_t cRxLock;

volatile int8_t cTxLock;:

/* 记录入队的数据项个数。
 * 即是需要解除多少个阻塞在发送等待列表中的任务。 */
volatile int8_t cTxLock;

cRxLock 和 cTxLock

当中断服务程序操作队列并且导致阻塞的任务解除阻塞时。
首先判断该队列是否上锁:

  • 如果没有上锁,则解除被阻塞的任务,还会根据需要设置上下文切换请求标志;
  • 如果队列已经上锁,则不会解除被阻塞的任务,取而代之的是,将 xRxLock 或 xTxLock 加 1,表示队列上锁期间出队或入队的数目,也表示有任务可以解除阻塞了。

cRxLock 对应待出队的个数。
cTxLock 对应待入队的个数。

触发解除阻塞

触发解除阻塞的方式:

  • 收发消息。

    • 即是数据项出入队时,会触发阻塞的任务解除阻塞。
  • 超时。

    • 超时也会触发对应的阻塞任务解除阻塞。
  • 解锁后处理上锁时未处理的出入队。

    • cRxLock 和 cTxLock。

附件-源码

/*
 * Definition of the queue used by the scheduler.
 * Items are queued by copy, not reference.  See the following link for the
 * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html
 */
typedef struct QueueDefinition
{
	int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */
	int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
	int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */

	union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
	{
		int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */
		UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
	} u;

	List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
	List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */

	volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
	UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
	UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */

	volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
	volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */

	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if ( configUSE_QUEUE_SETS == 1 )
		struct QueueDefinition *pxQueueSetContainer;
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxQueueNumber;
		uint8_t ucQueueType;
	#endif

} xQUEUE;
posted @ 2021-11-04 18:16  李柱明  阅读(512)  评论(0编辑  收藏  举报