嵌入式实时操作系统uC/os-II(十四)-消息队列

  • 消息队列

消息队列由三部分组成:事件控制块、消息队列、消息。当事件控制块成员OSEventType值为OS_OSEVENT_TYPE_Q时,该事件控制块代表一个消息队列。

         消息队列的数据结构如图6-1所示。从图中可以看到,消息队列相当于一个共用一个任务等待列表的消息邮箱数组,事件控制块成员OSEventPtr指向一个叫做队列控制块(OS_Q)的结构,该结构管理着一个数组MsgTbl[],该数组中的元素都是指向消息的指针。

 嵌入式实时操作系统uC/os-II(十四)-消息队列

                                         图6-1 消息队列的数据结构

  1. 消息指针数组

消息队列的核心部件为消息数组指针。图6-2表示消息指针数组的结构,其中各参数的含义见表6-1

                         嵌入式实时操作系统uC/os-II(十四)-消息队列

                         嵌入式实时操作系统uC/os-II(十四)-消息队列

                                                               6-2 消息指针数组的结构

其中,OSQInOSQOut为可移动的指针;OSQStartOSQEnd为常指针。当可移动指针OSQInOSQOut移动到数组末尾,也就是与OSQEnd相等时,可移动的指针将会被调整到数组的起始位置OSQStart。也就是说,从效果上看,指针OSQEndOSQStart等值。于是,这个由消息指针构成的数组就头尾衔接起来形成一个如图6-3所示的循环队列。

                                    嵌入式实时操作系统uC/os-II(十四)-消息队列

                                                                      6-3 循环队列

     可用2种方式向指针数组插入消息:先进先出的FIFO方式和后进先出的LIFO方式。当采用先进先出(FIFO)方式时,消息队列将在指针OSQIn指向的位置插入消息指针,而OSQOut指向的消息指针为输出;当采用先进先出(LIFO)方式时,则只使用指针OSQOut,当向队列插入消息指针时,指针OSQOut将先移动到图6-3所示的位置(虚线所示),在按指针OSQOut指向的位置插入消息指针,输出时则指针OSQOut不需要移动,其指向就是输出。

  1. 队列控制块

为了对图6-2所示的消息指针数组进行有效的管理,uC/OS-II把消息指针数组的基本参数都记录在一个叫做队列控制块的结构中。队列控制块的结构如下:

typedef   struct os_q{

         struct  os_q  *OSQPtr;

         void          **OSQStart;

         void           **OSQEnd;

         void           **OSQIn;

         void           **OSQOut;

         INT16U    OSQSize;

         INT16U    OSQEntries;

}OS_Q;

uC/OS-II初始化时,系统将按文件OS_CFG.H中的配置常数OS_MAX_QS定义OS_MAX_QS个队列控制块,并用队列控制块中的指针OSQPtr将所有队列控制块链接为链表。由于这时还没有使用它们,因此这个链表叫做空队列控制块链表。空队列控制块链表如图6-4所示。

                               嵌入式实时操作系统uC/os-II(十四)-消息队列

                                                                             图6-4 空队列控制块链表

每当任务创建一个消息队列时,就会在空队列控制块链表中摘取一个控制块消息队列来使用,并令该消息队列事件控制块中的指针OSEventPtr指向这个队列的控制块;而当任务释放一个消息队列时,就会将该消息队列使用的队列控制块归还空队列控制块链表。