NUCLUES操作系统消息传递机制(全面详尽的解释).doc_第1页
NUCLUES操作系统消息传递机制(全面详尽的解释).doc_第2页
NUCLUES操作系统消息传递机制(全面详尽的解释).doc_第3页
NUCLUES操作系统消息传递机制(全面详尽的解释).doc_第4页
NUCLUES操作系统消息传递机制(全面详尽的解释).doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

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

文档简介

关于消息映射机制的几点实习总结一、 事件、消息、消息队列和邮箱1事件事件是可以被控件识别的操作。比如,按下一个按钮,选择某单选框、复选框等。事件包括系统事件和用户事件。系统事件由系统激发,如时间每隔24小时,银行储户的存款日期增加一天。用户事件由用户激发,如用户点击按钮,在文本框中显示特定的文本。所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数).当然事件不仅限于用户的操作.。事件机制用于任务与任务之间、任务与ISR之间的同步。事件具有以下特点:(一)发行者确定何时引发事件,订户确定执行何种操作来响应该事件。(二)一个事件可以有多个订户。一个订户可处理来自多个发行者的多个事件。(三)没有订户的事件永远也不会引发。(四)事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。(五)如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。典型的事件操作:(一) 创建事件集(二) 删除事件集(三) 发送事件(集)(四) 接收事件(集)(五)获取有关事件集的各种信息 2消息 消息:内存空间中一段长度可变的缓冲区,其长度和内容均可以由用户定义,其内容可以是实际的数据、数据块的指针或空。对消息内容的解释由应用完成。从操作系统观点看,消息没有定义的格式,所有的消息都是字节流,没有特定的含义。从应用观点看,根据应用定义的消息格式,消息被解释成特定的含义。应用可以只把消息当成一个标志,这时消息机制用于实现同步。3消息队列消息队列可存放若干消息,提供了一种任务间缓冲通信的方法。消息机制可支持定长与可变长度两种模式的消息,可变长度的消息队列需要对队列中的每一条消息增加额外的存储开销。典型的消息队列操作有:(一)创建消息队列(二)发送普通消息(三)发送紧急消息(四)发送广播消息(五)接收消息(六)删除消息队列(七)获取有关消息队列的各种信息 4邮箱邮箱为任务之间的通信提供一种低消耗的机制。每个邮箱可以容纳控制一条消息。邮箱可以由用户动态创建和删除。二、 基于MAILHUBC的消息响应机制1. MailboxC的派生类:ApplicationC ApplicationManagerC DialogStackC SoftIconDisplayCGpteKeyProcessC WindowC2. 有关的宏BEGIN_MAIL_MAP(ThisClass, BaseClass)END_MAIL_MAP( ) DECLARE_MAIL_MAP( )DEFINE_TERMINATING_MAIL_MAP(ThisClass) ON_MAIL_NOARGS(MailMsgId, MailFunc)ON_MAIL_VOIDPTR(MailMsgId, MailFunc)ON_MAIL_MSGID_VOIDPTRON_MAIL_WINDOWMAIL(MailMsgId, MailFunc)3. 有关的函数MailHandlerResultT FindMailHandler(uint32 MailMsgId, void *MailMsgP);4. 消息映射的实现某个类(必须是MailboxC的继承类)添加一个消息映射,通常我们的做法是:第一, 为这个类定义一个消息,例如:#define SMSAPP_LAUNCH APPCAT(SMSAPP,1)第二, 为这个消息定义一个映射函数,如: MailHandlerResultT OnLaunchApp(void *MsgBufferP);第三, 将消息与函数关联起来,根据消息映射函数参数类型的不同,有三种方式,如下: ON_MAIL_VOIDPTR(SMSAPP_LAUNCH, SMSApplicationC:OnLaunchApp) ON_MAIL_NOARGS(VTUI_CLOSE_NOTIFY, MenuSettingDialogC:OnCloseNotify) ON_MAIL_WINDOWMAIL(VTUI_MENU_ITEM_HOVERED, MenuSettingDialogC:OnMenuItemHovered)5. 此外,一个类如果要实现消息映射机制,必须在声明文件(.h)的尾部使用宏DECLARE_MAIL_MAP( ),并在定义文件(.cpp)使用宏BEGIN_MAIL_MAP(ThisClass, BaseClass),END_MAIL_MAP(),而所有这个类的将消息映射函数与消息关联的消息映射宏都必须包含在这个两个宏中间。通过一个实际的例子把这些宏展开,就可以清楚地看到消息映射是如何实现的。这些宏的定义如下:#define DECLARE_MAIL_MAP( ) private: static const MailMapEntryT MailEntries ; protected: static const MailMapT MailMap; virtual const MailMapT* GetMailMap( ) const; #define BEGIN_MAIL_MAP(ThisClass, BaseClass) const MailMapT* ThisClass:GetMailMap( ) const return &ThisClass:MailMap; const MailMapT ThisClass:MailMap = &BaseClass:MailMap, &ThisClass:MailEntries0 ; const MailMapEntryT ThisClass:MailEntries = #define END_MAIL_MAP( ) 0, 0, END_HANDLER, (MailHandlerT)0 ; #define ON_MAIL_NOARGS(MailMsgId, MailFunc) MailMsgId, MailMsgId, NOARGS_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*)( )&MailFunc , #define ON_MAIL_VOIDPTR(MailMsgId, MailFunc) MailMsgId, MailMsgId, VOIDPTR_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*)(void*)&MailFunc , #define ON_MAIL_WINDOWMAIL(MailMsgId, MailFunc) MailMsgId, MailMsgId, WINDOW_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*)(uint32,WindowHandleT,ParamT,ParamT)&MailFunc , 我们取MenuSettingDialogC中的一部分代码展开作为实例来说明。这段代码是,DECLARE_MAIL_MAP ( )BEGIN_MAIL_MAP(MenuSettingDialogC, DialogC) ON_MAIL_NOARGS(VTUI_CLOSE_NOTIFY, MenuSettingDialogC:OnCloseNotify) ON_MAIL_WINDOWMAIL(VTUI_MENU_ITEM_HOVERED, MenuSettingDialogC:OnMenuItemHovered) ON_MAIL_VOIDPTR(VTUI_OPTION_SELECTED, MenuSettingDialogC:OnOptionSelected)END_MAIL_MAP( )第一句展开:/DECLARE_MAIL_MAP( )private: static const MailMapEntryT MailEntries;protected: static const MailMapT MailMap; virtual const MailMapT* GetMailMap( ) const;在这段代码里,宏DECLARE_MAIL_MAP( )声明了一个私有成员和两个保护成员,这是这个宏为什么必须放在类声明尾部的原因。如果放在中部和头部,这里的protected:很容易意外地把宏后的其它成员属性改为protected。这三个成员,都将在类的实现部分被宏BEGIN_MAIL_MAP(ThisClass, BaseClass)初始化或定义。第二句和最后一句展开:/BEGIN_MAIL_MAP(MenuSettingDialogC, DialogC) const MailMapT* MenuSettingDialogC:GetMailMap() const return &MenuSettingDialogC:MailMap; const MailMapT MenuSettingDialogC:MailMap = &DialogC:MailMap, &MenuSettingDialogC:MailEntries0 ; const MailMapEntryT MenuSettingDialogC:MailEntries = / END_MAIL_MAP() 0, 0, END_HANDLER, (MailHandlerT)0 ;首先注意到,两段代码的最后分别是和,这就是两个宏为什么必须成对的原因,如果不成对使用,编译器将会报告括号不匹配的错误。BEGIN_MAIL_MAP(MenuSettingDialogC, DialogC)宏的作用是初始化和定义前面DECLARE_MAIL_MAP()宏所声明的数据成员MailEntries ,MailMap和成员函数GetMailMap()。我们依次来讨论这三个成员的作用:1 MailEntries:MailMapEntryT结构体类型的数组,用于存放消息ID及与处理该消息的回调函数指针,类对消息的响应其实质就是对该数组的遍历。 MailMapEntryT结构的定义为,struct MailMapEntryT uint32 MailMsgId; uint32 LastMsgId; / If Handler handles a range of Ids. MailHandlerTypeT Args; MailHandlerT MailHandlerP; 2 MailMap:MailMapT类型的指针变量,通过它可以获得本类和基类中MailEntries消息映射数组的地址。 struct MailMapT const MailMapT* BaseMapP; const MailMapEntryT* MailEntryP;3 GetMailMap( ), const属性的成员函数,正象大多数const函数所做的,得到某个成员变量的值,这里是返回上述成员变量MailMap的值。END_MAIL_MAP()宏的作用,主要是实现MailEntries数组的正常结束,这里给该数组提供了一个结束标示0, 0, END_HANDLER, (MailHandlerT)0 ,并且保证不会出现,号错误。 剩下的三个宏其实是为消息提供三种不同类型的映射函数,也是为MailEntries数组添加数组元素,以下依次展开:/ON_MAIL_NOARGS(VTUI_CLOSE_NOTIFY, MenuSettingDialogC:OnCloseNotify)/这是为消息VTUI_CLOSE_NOTIFY关联一个不带任何参数的映射函数OnCloseNotify( )。 VTUI_CLOSE_NOTIFY, VTUI_CLOSE_NOTIFY, NOARGS_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*) ( )&MenuSettingDialogC:OnCloseNotify ,/ON_MAIL_WINDOWMAIL(VTUI_MENU_ITEM_HOVERED, MenuSettingDialogC:OnMenuItemHovered) /这是为消息VTUI_MENU_ITEM_HOVERED关联一个带Windows Mail参数的映射函数OnMenuItemHovered, 参数的结构为。 VTUI_MENU_ITEM_HOVERED, VTUI_MENU_ITEM_HOVERED, WINDOW_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*)(uint32,WindowHandleT,ParamT,ParamT)&MenuSettingDialogC:OnMenuItemHovered ,/ ON_MAIL_VOIDPTR(VTUI_OPTION_SELECTED, MenuSettingDialogC:OnOptionSelected)/这是为消息VTUI_OPTION_SELECTED关联一个带空指针参数的映射函数OnMenuItemHovered。 VTUI_OPTION_SELECTED, VTUI_OPTION_SELECTED, VOIDPTR_HANDLER, (MailHandlerT)(MailHandlerResultT(MailboxC:*)(void*)&MenuSettingDialogC:OnOptionSelected ,以上只是给出了一般性的说明,而要深入追查一个消息是如何跟一个函数关联起来的,还要看以下代码:union MailMapFunctions MailHandlerT GenericP; MailHandlerResultT (MailboxC:*WindowMailHandlerT)(uint32 MailMsgId, WindowHandleT WindowHandle, ParamT ParamA, ParamT ParamB); MailHandlerResultT (MailboxC:*NoArgsMailHandler)(void); MailHandlerResultT (MailboxC:*VoidPtrMailHandlerT)(void* MailMsgP); MailHandlerResultT (MailboxC:*MsgIdVoidPtrMailHandlerT)(uint32 MailMsgId, void* MailMsgP); MailHandlerResultT MailboxC:DeliverMail(uint32 MailMsgId, void *MailMsgP)/ UIASSERT(MailMsgP != 0); return FindMailHandler(MailMsgId, MailMsgP);MailHandlerResultT MailboxC:FindMailHandler(uint32 MailMsgId, void *MailMsgP)/传入的是消息ID和映射函数的参数指针,根据函数类型的不同,这个参数可能有不同的解释 uint16 EntryIndex = 0; MailMapFunctions MailHandlers;/注意这是一个联合体,用于存储映射函数的信息 MailHandlerResultT HandlerResult = CONTINUE_MAIL_DELIVERY; bool FoundHandler = FALSE; const MailMapT* MailMap = GetMailMap(); const MailMapEntryT* MailEntryP = NULL; WindowMailMsgT* WindowMailMsgP = NULL; /Get the current classes memory map /Then loop through looking for a match /If found then return the RESULT back. /Then get a pointer to the parents map and loop to the top do /取得的MailEntry数组的入口 MailEntryP = MailMap-MailEntryP; EntryIndex = 0;/从元素0开始遍历 while (MailEntryPEntryIndex.Args != END_HANDLER) & (!FoundHandler) /由此可以看到,其实mailboxC支持的是多个消息的映射,只不过我们通常把上下限设为一致,在这里我用使用了数组元素的第一和第二个域 if (MailEntryPEntryIndex.MailMsgId = MailMsgId) /取得当前元素的函数指针 MailHandlers.GenericP = MailEntryPEntryIndex.MailHandlerP; /根据args成员确定映射函数的类型,并调用相应的函数,使用了数组元素的第三和第四个域 switch (MailEntryPEntryIndex.Args) case NOARGS_HANDLER: HandlerResult = (this-*MailHandlers.NoArgsMailHandler)(); break; case VOIDPTR_HANDLER: HandlerResult = (this-*MailHandlers.VoidPtrMailHandlerT)(MailMsgP); break; case MSGID_VOIDPTR_HANDLER: HandlerResult = (this-*MailHandlers.MsgIdVoidPtrMailHandlerT)(MailMsgId, MailMsgP); break; case WINDOW_HANDLER: WindowMailMsgP =(WindowMailMsgT*)MailMsgP; HandlerResult = (this-*MailHandlers.WindowMailHandlerT)(MailMsgId, WindowMailMsgP-WindowHandle, WindowMailMsgP-ParamA, WindowMailMsgP-ParamB); break; FoundHandler = TRUE; EntryIndex+; /进入BASE CLASS 的MAP MailMap = MailMap-BaseMapP; while (MailMap != 0) & (!FoundHandler); return HandlerResult对于任何需要响应的消息, 调用该类的DeliverMail即可。 三、 Mailhub消息的分发。 MAILHUBC存在的价值是在单线程的体系下模拟了多线程的控制方式。实现的方式就是在32位的MSG ID中拿出一个位段(21-31)用于标志MSG所属的MAILBOX(CATIGORY),在分发消息之前先判断MSG的种类,然后发给合适的MAILBOX处理。任何想要通过mailhub分发消息的mailbox,都必须有个注册的过程,其实质是将mailbox的指针加入到mailhub的LinklistC成员变量mRegisteredMailboxes中,注销则是一个相反的过程,MailHub最多可以注册211个不同CATIGORY的MAILBOX。只有注册了的Mailbox,Mailhub才能辨别出属于它的MSG,并予以分发,这是一个遍历的过程。注册的过程在UITASK启动的时候就一一完成了。MSG分发的Send方式与Post方式:1. Send方式:用代码直接说明就很清楚Iterator = mRegisteredMailboxes.GetIterator ( );while (MailboxP = (MailboxC*)mRegisteredMailboxes.GetNext(&Iterator)

温馨提示

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

评论

0/150

提交评论