0411

来源:互联网 发布:中兴机顶盒安装软件 编辑:程序博客网 时间:2024/05/29 19:23

消息队列

  1. 消息队列是µC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送以指针方式定义的变量。因具体的应用有所不同,每个指针指向的数据结构变量也有所不同。为了使用µC/OS-II的消息队列功能,需要在OS_CFG.H 文件中,将OS_Q_EN常数设置为1,并且通过常数OS_MAX_QS来决定µC/OS-II支持的最多消息队列数。  
  2. 在使用一个消息队列之前,必须先建立该消息队列。这可以通过调用OSQCreate()函数(见6.07.01节),并定义消息队列中的单元数(消息数)来完成。  
  3. µC/OS-II提供了7个对消息队列进行操作的函数:OSQCreate(),OSQPend(),OSQPost(),OSQPostFront(),OSQAccept(),OSQFlush()和OSQQuery()函数。图 F6.7是任务、中断服务子程序和消息队列之间的关系。其中,消息队列的符号很像多个邮箱。实际上,我们可以将消息队列看作时多个邮箱组成的数组,只是它们共用一个等待任务列表。每个指针所指向的数据结构是由具体的应用程序决定的。N代表了消息队列中的总单元数。当调用OSQPend()或者OSQAccept()之前,调用N次OSQPost()或者OSQPostFront()就会把消息队列填满。从图 F6.7中可以看出,一个任务或者中断服务子程序可以调用OSQPost(),OSQPostFront(),OSQFlush()或者OSQAccept()函数。但是,只有任务可以调用OSQPend()和OSQQuery()函数。  
  1. <img src="http://img.blog.csdn.net/20170409172654846?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRnVua3lGcm9nODIxOTUxMjU5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">图 F6.7 任务、中断服务子程序和消息队列之间的关系——Figure 6.7  
  2. 图 F6.8是实现消息队列所需要的各种数据结构。这里也需要事件控制块来记录等待任务列表[F6.8(1)],而且,事件控制块可以使多个消息队列的操作和信号量操作、邮箱操作相同的代码。当建立了一个消息队列时,一个队列控制块(OS_Q结构,见OS_Q.C文件)也同时被建立,并通过OS_EVENT中的.OSEventPtr域链接到对应的事件控制块[F6.8(2)]。在建立一个消息队列之前,必须先定义一个含有与消息队列最大消息数相同个数的指针数组[F6.8(3)]。数组的起始地址以及数组中的元素数作为参数传递给OSQCreate()函数。事实上,如果内存占用了连续的地址空间,也没有必要非得使用指针数组结构。  
  3. 文件OS_CFG.H中的常数OS_MAX_QS定义了在µC/OS-II中可以使用的最大消息队列数,这个值最小应为2。µC/OS-II在初始化时建立一个空闲的队列控制块链表,如图 F6.9所示。  
  1. 队列控制块是一个用于维护消息队列信息的数据结构,它包含了以下的一些域。这里,仍然在各个变量前加入一个[.]来表示它们是数据结构中的一个域。  
  2. .OSQPtr在空闲队列控制块中链接所有的队列控制块。一旦建立了消息队列,该域就不再有用了。  
  3. .OSQStart是指向消息队列的指针数组的起始地址的指针。用户应用程序在使用消息队列之前必须先定义该数组。  
  4. .OSQEnd是指向消息队列结束单元的下一个地址的指针。该指针使得消息队列构成一个循环的缓冲区。  
  5. .OSQIn是指向消息队列中插入下一条消息的位置的指针。当.OSQIn和.OSQEnd相等时,.OSQIn被调整指向消息队列的起始单元。  
  6. .OSQOut是指向消息队列中下一个取出消息的位置的指针。当.OSQOut和.OSQEnd相等时,.OSQOut被调整指向消息队列的起始单元。  
  7. .OSQSize是消息队列中总的单元数。该值是在建立消息队列时由用户应用程序决定的。在µC/OS-II中,该值最大可以是65,535。  
  8. .OSQEntries是消息队列中当前的消息数量。当消息队列是空的时,该值为0。当消息队列满了以后,该值和.OSQSize值一样。 在消息队列刚刚建立时,该值为0。  
  9. 消息队列最根本的部分是一个循环缓冲区,如图F6.10。其中的每个单元包含一个指针。队列未满时,.OSQIn [F6.10(1)]指向下一个存放消息的地址单元。如果队列已满(.OSQEntries与.OSQSize相等),.OSQIn [F6.10(3)]则与.OSQOut指向同一单元。如果在.OSQIn指向的单元插入新的指向消息的指针,就构成FIFO(First-In-First-Out)队列。相反,如果在.OSQOut指向的单元的下一个单元插入新的指针,就构成LIFO队列(Last-In-First-Out)[F6.10(2)]。当.OSQEntries和.OSQSize相等时,说明队列已满。消息指针总是从.OSQOut [F6.10(4)]指向的单元取出。指针.OSQStart和.OSQEnd [F6.10(5)]定义了消息指针数组的头尾,以便在.OSQIn和.OSQOut到达队列的边缘时,进行边界检查和必要的指针调整,实现循环功能。  


0 0