第5章消息管理_第1页
第5章消息管理_第2页
第5章消息管理_第3页
第5章消息管理_第4页
第5章消息管理_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、嵌入式操作系统嵌入式操作系统与程序设计与程序设计第5章 消息管理5.1 消息邮箱5.1.1 建立消息邮箱5.1.2等消息5.1.3 发消息5.1.4 删除消息邮箱5.1.5放弃邮箱等待5.1.6 无等待请求消息5.1.7查询邮箱状态5.1.8 消息邮箱的例子5.2 消息队列5.2.1 消息队列数据结构5.2.2 初始化消息队列5.2.3 建立消息队列5.2.4发消息到消息队列5.2.5等待消息队列中的消息5.2.6删除消息队列5.2.7取得消息队列的状态5.2.8消息队列应用举例习题 在信号量、互斥信号量和事件标志组的内容结束后,读者对事件之间如何同步,如何根据不同需要设计同步程序,应该有了深

2、入的理解和提高。本章的消息管理中包括消息邮箱和消息队列两方面的内容,适用于任务之间的信息交流和同步。从原理上讲,消息管理也应该属于事件管理的范畴 。5.1 消息邮箱消息邮箱消息邮箱是C/OS-II中的另一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个消息。传递这个消息的媒体是一个指针型变量,该指针指向一个包含了“消息”的某种数据结构。 5.1.1 建立消息邮箱建立消息邮箱在系统初始化之后,并不存在一个消息邮箱。这时操作系统中的事件管理数据结构事件控制块ECB为全空,所有的事件控制块都在ECB空闲链表中排队。消息邮箱的建立函数OSMboxCreate将使用一个并配置一个ECB,

3、使其具备消息邮箱的属性。表5.2创建信号量函数OSMboxCreate解析 1.检查是否这中断服务程序中创建消息邮箱。同不允许在中断服务程序中创建信号量一样,操作系统C/OS-II同样不允许在中断服务程序中创建消息邮箱。2.检查是否有空闲的事件控制块。将OSEventFreeList赋值给pevent,如果pevent为空指针,表示没有空闲的事件控制块,函数返回。3.在事件控制块空闲链表中取下表头。因为pevent现在已经是用于邮箱的事件控制块,读者可以直接把他理解为一个邮箱。那么,需要执行的操作显然就是在事件控制块空闲链表中将他删除,这时候OSEventFreeList应该指向第二个ECB。

4、4.对事件控制块赋值假设信号量值为5,则赋值后的ECB应该如图5-1所示 5.返回ECB地址。 5.1.2等消息等消息等消息也称为请求消息。含义是当消息存在的时候获取消息,等消息也称为请求消息。含义是当消息存在的时候获取消息,当消息不存在的时候就放弃对当消息不存在的时候就放弃对CPU的占有,直到有消息的时的占有,直到有消息的时候才被唤醒。当任务后续的操作离不开消息,这时任务就不该候才被唤醒。当任务后续的操作离不开消息,这时任务就不该死死占着死死占着CPU不让其他的任务运行,就应该去休息,而当消不让其他的任务运行,就应该去休息,而当消息到来的时候系统会将消息唤醒回就绪态,任务获得消息后继息到来的

5、时候系统会将消息唤醒回就绪态,任务获得消息后继续运行。续运行。 表5.3等待消息邮箱函数OSMboxPend解析开开始始返返回回参参数数检检查查是是否否通通过过是是是否否p pm ms sg g是是否否不不为为空空否置置位位O OS ST TC CB BS St ta at t中中等等待待消消息息标标志志调调用用O OS S_ _E Ev ve en nt tT Ta as sk kW Wa ai it t终终止止当当前前任任务务,E EC CB B事事件件表表中中添添加加当当前前任任务务执执行行一一次次任任务务调调度度存存储储超超时时时时间间到到O OS ST TC CB BD Dl ly

6、y 及及等等待待状状况况OSTCBStatPend否 这这里里任任务务又又一一次次被被调调度度了了!从从阻阻塞塞态态回回到到就就绪绪态态又又被被调调度度 这这里里任任务务被被剥剥夺夺了了C CP PU U!进进入入阻阻塞塞态态!等等待待标标志志是是否否有有效效是如如果果是是资资源源满满足足而而结结束束等等待待,只只需需要要设设置置任任务务块块的的E EC CB B指指针针为为空空返返回回值值设设置置为为O OS S_ _T TI IM ME EO OU UT T任任务务仍仍不不能能使使用用资资源源是返返回回值值设设置置为为O OS S_ _N NO O_ _E ER RR R任任务务可可使使用

7、用资资源源p pe er rr r中中填填写写对对应应的的出出错错信信息息是是将将邮邮箱箱中中的的消消息息地地址址送送p pm ms sg g是是否否是是等等待待超超时时调调用用O OS S_ _E Ev ve en nt tT Ta as sk kR Re em mo ov ve e清清除除任任务务块块相相关关等等待待标标志志和和任任务务块块O OS ST TC CB BS St ta at t清清除除任任务务块块相相关关等等待待标标志志返返回回值值设设置置为为O OS S_ _E ER RR R_ _P PE EN ND D_ _A AB BO OR RT T任任务务仍仍不不能能使使用用资

8、资源源否5.1.3 发消息发消息当一个任务因为等待消息而被阻塞的时候,只有当其他任务发出了消息,被阻塞的任务才能被恢复到就绪态,从而获得消息后继续运行。阻塞的函数在前一节分析过了,发消息的函数为OSMboxPost,参数是消息类型的ECB的指针,以及消息的地址。 表5.4发消息函数OSMboxPost解析开开始始返返回回参参数数检检查查是是否否通通过过否否否将将消消息息放放入入邮邮箱箱是是是是否否有有任任务务等等待待该该信信号号量量是调调用用O OS S_ _E Ev ve en nt tT Ta as sk kR Rd dy y使使等等待待该该消消息息的的最最高高优优先先级级任任务务就就绪绪

9、执执行行一一次次任任务务调调度度返返回回值值进进行行相相应应设设置置,提提示示出出错错返返回回值值设设置置为为O OS S_ _N NO O_ _E ER RR R邮邮箱箱是是否否是是满满的的否返返回回值值设设置置为为或或O OS S_ _N NO O_ _E ER RR R是返返回回值值设设置置为为O OS S_ _E ER RR R_ _M MB BO OX X_ _F FU UL LL L5.1.4 删除消息邮箱删除消息邮箱当消息邮箱不再使用了,就应该尽快归还给系统,即将消息占用的ECB归还给ECB空闲链表以备它用。消息邮箱的删除函数是OSMboxDel。删除一个消息也要涉及方方面面,因

10、为可能有任务正在等待这个邮箱中的消息。 表5.5删除消息邮箱的函数OSMboxDel解析开开始始返返回回参参数数检检查查是是否否通通过过若若有有任任务务等等待待该该邮邮箱箱T Ta as sk ks s_ _w wa ai it ti in ng g= =T TR RU UE E否否则则为为F FA AL LS SE E是是OS_DEL_NO_PEND其其他他值值否否设设置置该该E EC CB B属属性性为为未未用用空空闲闲E EC CB B链链表表表表头头插插入入该该E EC CB B无无任任务务等等待待该该邮邮箱箱? ?根根据据o op pt t值值进进行行分分支支转转移移是否否OS_DE

11、L_ALWAYS使使所所有有的的等等待待该该信信号号量量的的任任务务就就绪绪设设置置该该E EC CB B属属性性为为未未用用空空闲闲E EC CB B链链表表表表头头插插入入该该E EC CB B若若有有任任务务等等待待该该信信号号量量执执行行一一次次任任务务调调度度5.1.5放弃邮箱等待放弃邮箱等待同放弃对信号量的等待类似,放弃等待邮箱也绝对不会是放弃本任务对邮箱的等待。放弃等待邮箱函数将放弃的是所有等待某邮箱的任务对该邮箱的等待或等待某邮箱的优先级最高的任务对邮箱的等待。表5.6放弃等待邮箱函数OSMboxPendAbort解析流程如下:1.检查事件控制块指针是否有效及事件控制块类型是否

12、有效。2.如果pevent-OSEventGrp为0说明没有任务等待消息邮箱,取消等待的任务数是0,返回0。3.否则根据参数opt(选项)进行分支转移,如为OS_PEND_OPT_BROADCAST,使用while语句循环地将等待该邮箱的每个任务用OS_EventTaskRdy来取消等待并使其就绪(除非任务还被挂起);如果为其他值则只将最高优先级的任务取消等待并就绪之。4.返回取消等待信号量的任务数。5.1.6 无等待请求消息无等待请求消息 在中断服务程序和有些用户任务中,需要无等待的请求消息邮箱。也就是说,到邮箱中取邮件,如果有邮件就获得邮件,如果没有并不阻塞自己,而是继续执行其他代码。OS

13、MboxAccept就是无等待的请求消息邮箱函数,参数是请求的消息邮箱的ECB指针。该函数的返回值是指向邮箱的指针,如果没有取得消息,那么就返回空指针。 表5.7无等待地请求消息邮箱函数OSMboxAccept解析 首先参数检查ECB是否有效,如果有效,将消息邮箱中邮件的地址OSEventPtr赋值给pmsg,然后清邮箱内容,返回获得的邮件的地址pmsg。这样,如果邮箱中有邮件,那么返回邮件的地址,如果没有,返回值就是空地址。 5.1.7查询邮箱状态查询邮箱状态 消息邮箱状态查询函数OSMboxQuery的参数是ECB地址和一个指向OS_MBOX_DATA类型的地址。ECB地址指向邮箱,OS_

14、MBOX_DATA类型的地址指向返回结果的一个S_MBOX_DATA类型的对象。表5.9查询消息邮箱状态函数OSMboxQuery解析Example5_1:task1任务每任务每1秒记录运行次数,发送到消息邮箱;秒记录运行次数,发送到消息邮箱;task2任务每任务每1秒从消息邮箱接收消息并打印。秒从消息邮箱接收消息并打印。消息邮箱例程消息邮箱例程 5.1.8 消息邮箱的例子消息邮箱的例子假设有任务TaskMessageSen和TaskMessageRec, TaskMessageSen在事件片1创建一个邮箱,如果邮箱中已没有邮件,每秒向邮箱发送一个消息,消息内容为从0开始的计数值,该计数值每秒

15、加1。任务TaskMessageRec从时间1开始,做的事情就是查看邮箱,然后把邮件打印出来。现在我们采用邮件管理完成这两个任务的设计。5.2 消息队列消息队列 消息邮箱中只能存放一则消息,太少了,能不能像电子邮件一样,管理多条消息呢? C/OS为实现这一目的,设计了消息队列管理。使用消息队列管理,就允许使用可以容纳多条信息的大邮箱,按照先进先出(FIFO)的原则,发送和接收邮件。需要注意的是,这样的邮箱不是操作系统提供的,而是要由用户任务来提供。操作系统提供的是对其进行管理的程序。另外,邮箱中的内容仍然是邮件的地址。 消息队列的代码单独存放在os_q.c中5.2.1 消息队列数据结构消息队列

16、数据结构1消息队列及其控制块消息队列及其控制块typedef struct os_q /* 队列控制块队列控制块QCB*/ struct os_q *OSQPtr; /*在空闲在空闲QCB链表中,指示下一个链表中,指示下一个QCB*/ void *OSQStart; /*队列数据的首地址队列数据的首地址*/ void *OSQEnd; /*队列数据的末地址队列数据的末地址*/ void *OSQIn; /*指示下次插入消息的位置指示下次插入消息的位置 */ void *OSQOut; /* 指示下次提取消息的位置指示下次提取消息的位置*/ INT16U OSQSize; /*队列的最大容量队列

17、的最大容量*/ INT16U OSQEntries; /*队列中当前的消息量队列中当前的消息量*/ OS_Q; 2消息控制块实体消息控制块实体 OS_Q OSQTblOS_MAX_QS;3空闲消息队列链表 消息控制块QCB中OSQWaitList用来指示空闲消息控制块QCB链表中的下一个消息控制块QCB。 5.2.2 初始化消息队列初始化消息队列 消息队列初始化函数在操作系统初始化时被调用,主要用于初始化消息队列使用的数据结构。消息队列初始化函数的名称为OS_QInit表5.13消息队列初始化函数OS_QInit解析1. 将所有QCB全部清为全0。2. 使用for循环将除最后一个消息控制块OS

18、QTblOS_MAX_QS - 1之外的所有消息控制块初始化,构建了单向的消息队列空闲链表。3.初始化最后一个QCB,将消息队列空闲链表完善。 5.2.3 建立消息队列建立消息队列 创建消息队列就是将从ECB空闲链表中取下一个事件控制块ECB来,将其用于消息队列管理。并从QCB空闲链表的表头取下一个消息控制块QCB,将其各种属性进行设置,用于指示消息的位置以及提取和插入消息的位置。创建消息队列的函数名称为OSQCreate。表5.14消息队列创建函数OSQCreate分析 1. 判断是否在中断服务程序中调用本函数,如果是就返回。2. 取得消息队列的链表首地址送pevent。3. 判断peven

19、t是否为空指针,如果是则说明是系统已经没有空闲的ECB可供使用,填写错误信息,返回空指针。4. 从空闲ECB链表取下表头。5. 空闲QCB链表首地址送pq。6. 如果没有有效的空闲QCB链表,恢复空闲ECB链表,返回空ECB指针。7. 在空闲QCB链表中取一个pq指向的QCB,对其进行初始化。设置OSQStart为消息指针数组的首地址start。OSQEnd值为&startsize即消息指针数组(消息队列)中最后一个指针后面的一个地址。OSQIn和OSQOut也设置为start。OSQSize的值为size。OSQEntries为0表示该队列中还没有消息。8. 接下来对pevent指向的ECB

20、进行初始化。OSEventType为OS_EVENT_TYPE_Q表示用于消息队列管理。OSEventCnt在这里没有用,设置为0。OSEventPtr指向QCB,即设置为pq。调用OS_EventWaitListInit初始化ECB中的事件等待表和事件等待组。9.返回ECB指针。5.2.4发消息到消息队列发消息到消息队列 发消息到消息队列的函数名称为OSQPost。参数是事件控制块ECB的地址pevent和消息的地址pmsg。表5.15发消息到消息对列函数OSQPost分析 1.首先进行参数检查,如果参数检查失败则返回。2. 如果有任务等待消息队列中的消息,那么消息队列现在必然是空的。不需要

21、将消息存入队列,而直接将消息给在等待的优先级最高的消息,并将其就绪。执行一次任务调度然后返回。3. 如果没有任务等待消息队列中的消息,那么就需要将该消息加入消息队列。如果消息队列是满的,不能容纳更多的消息,返回出错信息。否则,在消息控制块QCB的OSQIn所指示的消息指针数组位置存入该消息,然后将OSQIn 指向下一个单元以便下次使用。判断OSQIn是否到超过了表尾,如果超过了,将其指向队首。然后返回。5.2.5等待消息队列中的消息等待消息队列中的消息 等待消息队列的消息是消息队列管理中的又一核心函数。如果消息队列中有消息,那么就取出消息,然后返回;如果没有消息,只有在ECB中标记自己的等待,

22、然后阻塞。等待消息队列的函数的名称为OSQPend,参数是ECB的指针、等待超时时间和返回函数执行信息的指针的perr。函数的返回值是指向消息的指针。表5.16消息队列等待函数OSQPend分析1.首先进行参数、ECB类型、中断、调度锁检查,失败则返回。2. 取得ECB中的QCB指针,查询消息队列中是否有消息。如果有消息,那么请求直接成功,取得消息队列中OSQOut所指的消息,将OSQOut指向消息队列中的下一个元素以备下一次的消息提取。如果OSQOut指向了消息队列之外,就指向消息队列的首地址。将OSQEntries减1表示消息数量减少了一个。然后返回消息的指针。3. 如果没有消息,那么任务

23、就只有被阻塞。首先在TCB中的STCBStat中添加消息队列等待标志,任务延时时间,初始化等待状态,然后调用OS_EventTaskWait 添加等待标志和取消就绪标志,接着调用OS_Sched执行一次任务调度。 4. 任务恢复运行后,根据TCB中的等待状态OSTCBStatPend决定程序走向。如果获得了消息,进行一些处理后返回该消息。如果是退出等待,或是等待超时,分别填写没有取得消息的原因,然后返回空指针。5.2.6删除消息队列删除消息队列 当消息队列不再使用了,就应该尽快归还给系统,即将消息占用的ECB归还给ECB空闲链表以备它用,将QCB也归还给空闲QCB链表。删除消息队列的函数的名称

24、为OSQDel,参数是ECB的指针、删除操作的选项opt和返回函数执行信息的指针的perr。 其中opt的值为 OS_DEL_NO_PEND 表示只有当没有任务等待该消息队列的时候才允许删除,opt的值为OS_DEL_ALWAYS 表示无论如何都删除。如果成功删除,返回空指针;否则返回ECB的指针。表5.17消息队列删除函数OSQDel解析 1.首先进行参数的检查。2. 根据选项opt决定程序的分支3. 如果opt不是这两个值当中的一个,那就是说明是错误的选项,也属于参数检查失败。因此,标记错误信息perr为OS_ERR_INVALID_OPT后,直接返回原来ECB指针pevent。 5.2.7取得消息队列的状态取得消息队列的状态 消息队列数据OS_Q_DATA是为返回消息队列信息而提供的,因此用户程序如果想了解消息队列的信息,要先创建OS_Q_DATA的实例。然后以消息队列所在ECB地址及该实例的地址为指针为参数调用获取消息队列的状态函数OSQQuery表5.19获取消息队列的状态函数OSQQuery解析5.2.8消息队列应用举例消息队列应用举例假设有任务假设有任务TaskQSen和和TaskQRec, Task

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论