《匠人手记》推荐网上购书渠道:
EDN网(ednchina)购书入口   >>>
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历

百宝专栏

  • 首页 相册 标签
  • 电脑应用(65)
  • 供需信息(22)
  • 写书近况(82)
  • 匠人文集(115)
  • 硬件技术(171)
  • 匠人公告(86)
  • 与非门专栏(545)
  • 匠人笔记(115)
  • 团队撰写(96)
  • 汽车电子(52)
  • 编程技巧(465)
  • 程序宝典(476)
  • 网络酷文(472)
  • 开发工具(19)
  • 资料宝藏(274)
  • 项目管理(11)
  • 藏经宝阁(42)
  • 趣味设计(5)
  • 社区热贴(2)
  • 比尔盖茨熊专栏(0) 
  • 百宝信息

    载入中...

    百宝流量

    (2006-07-01开始)



    匠人手记

    消息驱动机制(转贴)
    程序匠人 发表于 2008-1-3 12:15:00  阅读全文 | 回复(0) | 引用通告 | 编辑

     消息驱动机制
                                   2005/01/29  asdjf@163.com  www.armecos.com
    yy20050129-1v1

        计算机本质上是信息处理机,输入数字化的数据,按照程序规定的步骤进行处理,输出指定的动作和时序,从而完成控制任务和信息处理。这里的关键是信息的输入,有了输入,后续处理和输出是水到渠成的事。那么怎样高效率地得到输入信息呢?有一种叫做消息驱动的机制可以比较完美地实现这个目的。
        
        消息有两层含义:1、消息发生的时间点(事件,动态概念);2、消息内容(信息,静态概念)。消息发生触发一个事件,用以主动通知信息的到来。有实际意义的系统中消息发生时间是随机的,由OS异步捕获此事件,再分发给对应的处理程序。之所以由OS负责通知消息,而不是由应用程序自己捕获,盖OS掌控系统的全部资源,一切事件均应知会OS,以便其全面参与系统管理。消息内容就是信息本身,是计算机的输入数据源,是实际要处理的内容。
        
        信息处理是计算机的灵魂,消息就代表到达的信息。利用消息驱动计算机输入的机制,显得自然、简洁、富有美感。程序的作用是事先编排好信息到达后的处理流程,但是信息何时到达却不能事先预测。也就是说,程序员可以预知所有可能的信息范围,但无法肯定哪个信息一定会到,何时到。这种情况导致两种处理方法:被动轮询和主动通知。消息属于主动通知一类。
        
        在硬件中,控制电路由有限状态机(FSM)实现,在软件中,消息处理由有限消息机(FMM)实现。关于竖着写的FSM和横着写的FMM,在《状态机的两种写法》一文中有详细说明,此处不再赘述。消息按到达次序被缓存在先入先出(FIFO)队列中(可以根据消息的实时性要求将消息队列分成高低两个优先级,但本质上消息还是要按照次序排队),依次由接收程序串行处理。
        ==============
        *消息是什么?*
        ==============
        --------------
        |消息就是对象|
        --------------
        他有自己的属性(成员)和方法(动作),同时隐含代表信息到达事件。当发生msg.event事件后,程序开始处理消息体msg.body,怎么处理?调用初始化时注册的回调函数msg.callback。即:if( msg'event ) msg->callback(msg->body);。消息主动通知OS信息到达,并自行给出处理方法,甚至自己选择下一步的目的地。这样信息就有了生命力,可以自主流动,自行工作。消息驱动就是要给信息的流动提供一种机制,他可以分发消息,缺省处理消息,销毁消息,异常处理,按指定动作处理消息。一旦实现这种机制,能够普适所有的消息处理情况,增改删操作不过就是实现新的消息和动作罢了,机制完全不必变化。从很小的系统到很大的系统,这种机制都能很好地适应,因为他们的本质都是为信息的流动提供一个通用平台。
        在PPP协议框架实现中,为节省代码量,LCP和IPCP复用同一个协商状态机FSM,完成相同的请求(req)、确认(ack)、否定(nak)、拒绝(rej)等一系列动作,LCP和IPCP可以看成协商状态机FSM的类实例。他们的动作完全相同,但属性,即协商的内容不同,一个是用于链路控制的选项协商,一个是用于NCP为IP协议时,IP地址、子网掩码、DNS1、DNS2的协商。在初始化时,将LCP的FSM回调函数注册为LCP的消息处理函数,将IPCP的FSM回调函数注册为IPCP的消息处理函数。当LCP消息到达时,FSM调用LCP注册的回调动作处理LCP的消息内容。回调函数准确地给出了当特定消息发生时要执行的私有动作,OS仅仅起到消息转发和通知的作用,他不提供专有的消息处理,而消息是对象,他本身就有处理私有属性的方法。从消息驱动的角度,PPP协议框架就是一堆消息对象的集合。当拨号成功时产生lowerup(底层已备)消息,通知PPP开始协商,LCP用req/ack/nak/rej消息协商链路选项,然后用约定的认证协议鉴权,继而IPCP获得IP地址信息,产生ipcpup消息,此时ip_input入口开始接收ip_arrive消息,并根据协议类型依次转发IP包消息到icmp_input、igmp_input、udp_input、tcp_input、raw_input等入口点。
        在Windows的设备驱动模式WDM中,引入了驱动程序对象和设备对象概念,利用I/O请求包IRP在各层设备对象(xDO:FDO/FilterDO/PDO)间传递设备控制消息。I/O管理器将上层打开open,关闭close,I/O操作ioctl,读read,写write等操作转化为IRP消息传到核心层,核心层的设备驱动在DriverEntry入口点注册消息回调函数,完成对即插即用PNP、电源管理PM、上层IRP设备控制、WMI等消息的私有处理。每个设备对象都可以申请自己的设备扩展内存区,以便保存私有数据。撰写win设备驱动,就是在写回调函数,只不过win已经定义好大部分消息,我们只要提供对应的处理程序即可。常常感觉win编程不过就是在实现一坨一坨的动作代码,然后就等着win发消息来调用,再就是满眼的switch/case语句分别处理不同的消息。程序员的责任是选择正确的系统API函数,保证动作执行准确无误。除了内存在保护模式下映射来映射去,硬件串行化访问,DMA和中断处理,各种总线驱动API,各种协议驱动,剩下的就全是消息处理了。值得一提的是完成例程的设置IoSetCompletionRoutine,通过设置完成回调例程和上下文私有数据区,我们可以拦截下层消息。因为下层何时能完成处理的时间不确定,如果程序死等I/O处理完成将浪费大量CPU处理能力。如果设置回调后挂起,让出CPU,等到I/O处理完成后再被激活,那么这种程序结构是最合理的。例如在批量USB处理时,URB缓冲区可能装不下整个发送数据,需要分片传递。方法就是设置好完成回调,然后把IRP传到下层,挂起。一旦下层完成USB收发,就会发消息激活完成回调,完成回调根据保存的上下文实现分片传输,直至完成全部数据传送,然后向上层发消息通知I/O处理完毕。
        类似消息激活在智能网程序里也有体现。主叫用户摘机后播放提示语音,在此期间如果用户拨号,马上停止放音。难点是不知用户何时拨号。如果设定一个固定延时,用户会感觉非常不友好。如果定时轮询用户是否拨号,至少要百毫秒周期,当用户量上到一万以上的时候,这种方式浪费太大。现在的放音机制是发个消息给语音板和交换网络,让其给主叫摘机用户放音,然后定时监视收号器,判断用户是否拨号。这样做用户数量不能做大。怎么办呢?和WDM的完成回调一样,创建一个信号量,发完放音消息后就把此信号量句柄连同post回调一起放在消息里发给收号器,然后挂起,超时等待在此信号量上,一旦收号器在任意时间收到用户拨号,就会把拨号消息反馈回来,系统调用我注册的私有Post回调响应此消息时就会释放此信号量,我的主程序就被唤醒激活,一点也不浪费CPU处理能力。而且超时机制能保证异常时的恢复。
        对于这种不确定时延的操作,使用消息驱动机制是非常有效的。例如:TCP协议使用connect原语建立连接,但是连接何时建立事先并不知道,也许信道质量好,三次握手很快就完成了;也许信道误码率高,拖延了很长时间才连上;甚至因重连次数大于6次而导致连接失败。在lwip实现中,应用层调用connect函数进行主动连接,在该函数内部实际上是生成一个消息发送给tcpip_thread线程,在此消息里包含了conn->mbox信号量句柄,然后,该函数阻塞等待在此信号量上。一旦底层完成三次握手,连接成功,就会触发TCP已连接事件TCP_EVENT_CONNECTED回调do_connect释放此信号量,connect随即退出阻塞。在应用层看来,connect一直阻塞到连接成功,如果不成功就返回-1。connect运行在用户线程,实际连接运行在tcpip_thread线程,通过消息回调,使两个不同线程的函数建立了同步关系,虽然TCP协议时延动态范围很大,达到秒级,但这种消息驱动机制能很好地适应变化。
        --------------------
        |消息就是串行化处理|
        --------------------
        多任务并行处理的好处是改善并发特性,提高实时性。但代价是需要处理同步、互斥、重入、阻塞等新问题。OS切换时间一般是10ms的整数倍,如果只有几百个进程(或以下),多任务的工作性能会有很好的表现。然而难以想象上千上万的进程同时工作的情形,那是注定要崩溃的。因此,Windows的TCP/IP协议栈使用“完成端口”技术自行管理socket连接,而不是每次接收(accept)到新socket连接就创建新线程。同样,Linux里也使用select管理多个socket连接。这样连接数可以做得很大,而性能又不会急剧下降。总之,用多任务方式不能实现大容量系统。由于串行化处理不存在并行,也就不会遇到同步、互斥等问题,一切处理都简单了,而且,没有任务切换,效率也高。需要注意的是,因为消息排在队列里,所以,队列空间一定要充足,否则当队列满时,消息会丢失。如果消息收发在同一进程,还有可能造成死锁。lwip移植中就会遇到此问题,因为lwip为了兼容不带OS的情况,把消息收发做在了一个线程里,以便有/无OS时都能正常工作,当消息队列满时,发阻塞,收也被阻止,必然死锁。建议消息收发尽量放在不同进程里,以免死锁。实在不行,也要尽可能加大队列空间。另外注意划分任务优先级时把等待消息的线程设高,以免队列中堆积消息太多而溢出。当然,消息驱动最好基于OS,因为OS实现的队列自动具有互斥功能,使用方便,挂起的任务也不浪费CPU时间片。我说的串行化处理不是整个系统都是串行的,那样就是前后台系统了,我说的是在多进程的某一个进程里实现串行化。
        --------------
        |消息就是任务|
        --------------
        上面所说的串行化处理可以大大提高系统处理容量,但是当容量达到一定数值时,内存和总线瓶颈会限制容量的进一步增长(例如静态双口RAM读写时延为7ns)。为了进一步提高吞吐率,必须将单CPU处理模式转换成阵列处理,以便突破系统瓶颈。在多任务系统中,堆栈保存了任务的现场信息,通过保存和恢复现场,我们可以实现多任务切换。同样,消息中也保存了完整的现场信息,自然可以看成独立的任务,只不过原来的任务现场信息保存在堆栈里,现在的任务现场保存在队列中。我们可以设想把当前任务的现场保存在消息里,然后把消息发送到目的地,由接收者在自己的系统空间中恢复任务现场,只要信息不丢失,任务就能在这里复活。有些系统应用程序和OS分离,应用程序通过软中断调用系统API,即OS可以动态加载应用程序;还有一些系统实现了虚拟机,隔离了硬件,屏蔽了平台差异,应用程序可以跨平台执行。在这些系统上,可以借助消息机制,使任务在不同平台间移动。例如:从主处理机移动到子处理机上执行,从中心处理机移动到边缘处理机等,从而减轻中心内存和主CPU的压力。确保安全的前提下,阵列中的各处理机并行工作,打破了速度瓶颈,信息象水一样地流来流去。
        --------------
        |消息就是信件|
        --------------
        在HJD04程控电话交换机里,我们把消息形象地称为信件。
        考虑日常工作中的例子:采购了一批电子器件,首先要填好入库申请单,呈负责人签字同意,然后到财务那里报账,财务再签章,最后带着器件找库管入库,库管核验通过后签字。这时,一式三份的入库单自己留一张,库管一张,财务一张。在整个过程中共有4人参与:我、负责人、财务、库管。除我之外,另外三人并不同时在场,甚至可能不在同一时间出现(例如,第一天找负责人,第二天找财务,第三天找库管),但这并不妨碍我顺利办理器件入库,只要我有入库单在手。整个过程中,3个人通过入库单建立了联系:负责人审批,财务入账,库管入库。换句话说,入库单将3人耦合到了一起。不过3人不存在直接调用,也没有复制入库单副本,而是全凭单子上的签章作业。这样,每个人(处理机)在处理入库单(消息)后,签上字(增加消息内容),然后发给下一个人,自己再去干别的,而过程中自己并不保留入库单副本(临时中间变量)。尽管每个人都没有刻意记住曾经签过字(只在签字前花些时间思索了一下,过后可能就忘了),但是入库单上保存了所有信息,入库工作会有条不紊地按程序进行。3个人可能都不知道完整的事态发展,但他们只要在自己的工作范围内付出一些处理能力,就能促进整个任务的完成。
        04交换机采用阵列处理,消息驱动机制,处理能力等效20万用户线。当主叫摘机后产生主叫摘机信,信中存有主叫号码,用户级别等信息。主机收到此信后批示申请资源(交换网络和收号器),然后将其转发给交换网络板,网络板查找空闲链路,登记为占用,并在信中批注网络资源申请成功和链路号。将此信转给记发器板,记发器板查找空闲收号器,登记为占用,并在信中批注收号器申请成功和记发器号。最后,此信又传回了主机。主机了解到资源全部申请成功,就命令向主叫发拨号音并给记发器板发收号监视信,以便收号结束后传回收号结果。此过程中各个子处理板并不保留中间信息,如用户信息,结果信息等。所有信息全部保存在信里。各子处理板处理完信件,会立即忘掉刚才处理的内容。跳过中间处理过程的叙述,一旦被叫摘机,会立即产生主叫计费开始信,此后任何一方挂机将产生计费结束信。计费台根据主被叫号码,用户级别,时段,节假日,起止时间等分段计算费用,并将话单存入数据库。为了防止进程死机,设计了一个高优先级监控进程,其他各进程定期向监控进程发联络信,说明自己是谁,表明自己还活着。一旦超时未收到联络信,监控进程就重启那个死掉的进程。
        采用信件处理的方式易于理解和实现。信件可以生成、销毁、转发、回复、修改、复制,给实际操作带来了便利。只要增加新的信件种类就可以扩充系统功能,而处理机制仍然保持不变。
        
        在消息驱动的系统中,内存非常关键,不能出错。硬件上采用双机热备份,实时纠错等手段,能够提高系统稳定性。对于有限的内存空间,最好使用动态内存管理。

    看《匠人手记》,与匠人同行!北航出版,正在热卖!

  • 标签:消息驱动 
  • 发表评论:
    载入中...

    芯片专题

    器件专题

    软件专题

    硬件专题

    综合专题

    项目专题

    原创专题

    器件检测
    LCD LED
    按键 触摸键
    E2PROM
    电池 电机
    电阻 电容 电感

    指令系统
    软件算法
    编程规范
    滤波算法
    串行通讯

    PCB设计
    I2C PWM
    红外遥控
    充电技术
    中断 ADC 

    匠人手记
    匠人夜话
    网络心路
    一周热点串烧
    从零开始玩PIC
    DIY旋转时钟

    广告5号位 [投放]


    学习板、开发板、编程器、下载器、仿真器(查看详情……)

    站内搜索


    站外搜索


    百度  google
    mp3  歌词 
    图片  FLASH 
    知道  文档
    新闻  词典 
    地图  mp3 
    软件  天网 
    雅虎  爱问 
    搜狗  讯雷 
    网讯  华军 
    天空 

    21IC器件搜索
    百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     
     

    新鲜货色

    匠人手记

    近期动态

    载入中...

      《匠人手记》购书全攻略 
     书友近况:淘书手记答疑与讨论:什么是散转程序 
     《匠人手记》新书艳照
     EDN《匠人手记》签名售书优惠活动开始报名啦!
     欢迎加入《匠人手记》EDN书友会
     欢迎加入《匠人手记》书友会Q群
     《匠人手记》终稿目录
     《匠人手记》封面,请大家先睹为快
     上周六收到了北航寄来的《匠人手记》清样,让大家先睹为快

    匠人原创

    粉丝评论

    往日酷贴

    载入中...

    载入中...



     网络酷文:博客,改变的不仅仅是图书 
     网络酷文:C语言宏定义技巧C语言 条件编译详解

      21IC上海2008-04聚会报名进行中。。。 
     两分钟让你明白什么是ERP![转]
      神奇的Duff's Device 算法
      实用一线通讯电路及软件设计方法
      程序员的“七年之痒”
      史上最短但最精彩的武侠小说
      网络无厘头文学《缺钙水浒》(爆笑)

     你的博客还能持续多久(转贴)
     电动车无刷电机控制器软件设计要点(作者:谢渊斌)

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!