2.1 消息队列控制块
来看一下消息队列控制块(结构体)的结构组成:
FreeRTOS的消息队列控制块由多个元素组成,当消息队列被创建时,系统会为控制块分配对应的内存空间,用于保存消息队列的一些信息如消息的存储位置,头指针pcHead、尾指针pcTail、消息大小uxItemSize以及队列长度uxLength等。
每个消息队列都与消息空间在同一段连续的内存空间中,在创建成功的时候,这些内存就被占用了,只有删除了消息队列的时候,这段内存才会被释放掉,创建成功的时候就已经分配好每个消息空间与消息队列的容量,无法更改,每个消息空间可以存放不大于消息大小uxItemSize的任意类型的数据,所有消息队列中的消息空间总数即是消息队列的长度,这个长度可在消息队列创建时指定。
union /* 使用联合体用来确保两个互斥的结构体成员不会同时出现 */ { int8_t *pcReadFrom; /* 当结构体用于队列时,pcReadFrom指向出队消息空间的Zui后一个 */ UBaseType_t uxRecursiveCallCount;/* 当结构体用于互斥量时,uxRecursiveCallCount用于计数,记录递归互斥量被“调用”的次数 */ } u;
List_t xTasksWaitingToSend; /* 一个发送消息的阻塞列表,用于保存阻塞在此队列的任务,任务按照优先级进行排序,由于队列已满,想要发送消息的任务无法发送消息 */ List_t xTasksWaitingToReceive; /* 一个获取消息的阻塞列表,用于保存阻塞在此队列的任务,任务按照优先级进行排序,由于队列是空的,想要获取消息的任务无法获取到消息 */
volatile UBaseType_t uxMessagesWaiting;/* 记录当前消息队列的消息个数,如果消息队列被用于信号量的时候,这个值就表示有效信号量个数*/ UBaseType_t uxLength; /* 队列的长度,也就是能存放多少消息 */ UBaseType_t uxItemSize; /* 单个消息的大小 */
volatile int8_t cRxLock; /* 队列上锁后,储存从队列收到的列表项数目,也就是出队的数量,如果队列没有上锁,设置为 */ volatile int8_t cTxLock; /* 队列上锁后,储存发送到队列的列表项数目,也就是入队的数量,如果队列没有上锁,设置为 */
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) uint8_t ucStaticallyAllocated; /* 如果队列使用的内存是静态分配的,以确保不会尝试释放内存,则设置为pdTRUE */ #endif
#if ( configUSE_ == 1 ) struct *px; /* 队列集 */ #endif
#if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t ux; uint8_t uc; /* 队列的类型(用途) */ #endif
} xQUEUE;
/* 旧版本的FreeRTOS使用xQUEUE,新版本使用代替*/typedef xQUEUE ;
队列的类型定义:
ASE即基本的消息队列,另外,信号量机制也是通过队列实现的,因此当用于互斥信号量,二值信号量等时,会标记对于的队列类型。