• NS2中事件调度过程浅析


    NS2中事件调度过程浅析

    最近研究NS2仿真工具,在学习源代码的过程中查看了一下NS2中的事件调度相关内容,对其流程有了一些粗浅认识,特分享如下。本人新手,以下内容有错误和不足之处恳请指教:)

    1. 事件调度相关类简介
    类结构如图1所示:


    图1 NS2事件调度相关类结构图



    重要类简介:
    1)        Handler类:
       定义位置:~\Common\Scheduler[.h .cc]
       作用概述:
             NS2中用于执行对事件的处理动作(在handle()方法中实现);
             作为Event类的属性,所有的事件都会保存用于处理自己的Handler,以供分派(dispatch)时使用;
       属性/方法概述:
             public virtual void handle(Event * event);  
                      /*Handler类中的唯一一个方法,用于处理事件,其子类根据具体事件处理要求来实现(例如NSObject的handle方法); */ 

    2)        Event类:
       定义位置:~\Common\Scheduler[.h .cc]
       作用概述:
             作为NS2事件调度机制的重要组成,是所有事件的父类(例如Packet类就是其子类);
       属性/方法概述:
             public Event* next_;          //用于生成事件链表
             public Event* prev_;
             public Handler* handler_;    //用于记录该事件的处理器,也就记录了处理方法 

    3)        NSObject类:
       定义位置:~\Common\Object[.h .cc]
       作用概述:
             继承自Handler类,因此其子类可以作为参数传递给Scheduler::schedule()方法,以便之后处理事件时调用其handle方法;
             各种Connector类通常继承自此类;
       属性/方法概述:
             protected void handle(Event* e); /*实现父类handle方法,只有一句代码:recv((Packet*)e);*/
             protected void recv(Packet *p, const char*);    //直接调用Packet::free(p); 

    (介绍了上面三个类,接着就可以看看它们是被什么类使用、如何被使用的了)
    4)        Scheduler类:
       定义位置:~\Common\Scheduler[.h .cc]
       作用概述:
             一个以时间为触发条件的离散事件调度器,NS2事件调度机制的基础; 
             完成事件的出/入队列、维护、分发等;
             具有三个具体实现的子类(NS2通常默认为CalendarScheduler);
       属性/方法概述:
             public void schedule(Handler*, Event*, double delay)   //代码摘录如下
                      {
                         ...//判断参数有效性
                         e->uid_ = uid_++;
                         e->handler_ = h;
                         double t = clock_ + delay;
                         e->time_ = t;
                         insert(e);
                      }
    /*从上即可知道schedule如何使用了Handle和Event类对象:设置事件id、处理时间以及handler,并将事件加入调度队列;也由此可以知道之前一直作为参数传递的Handler到此就被赋值给了Event的handler_,即实现了处理器和事件的“绑定”*/
             public virtual void run();
    /*只要调度队列中还有事件待处理,则一直分派(dispatch)事件队列中的事件;*/
             protected void dispatch(Event*, double);
    /*在特定时间调用与事件绑定的Handler的handle()方法处理事件自己;*/
      

    2. 事件调度过程举例
    结合以上内容,举例说明Packet的从Channel传递到Phy的调度过程,如图2所示:



    图2 事件调度过程示意图




    1)        在Channel::sendUp(Packet* p, Phy *tifp)方法中最终会调用s.schedule(rifp, newp, propdelay)方法,其中s为Scheduler实例,rifp为Phy*,newp为Packet*;
    2)        Scheduler获得该Packet后先判断参数有效性判断,然后执行newp->handler_ = rifp以保存该包的处理器(即Phy对象),然后insert入队列;
    3)        当调度到该Packet后,执行dispatch(Event* p, double t)方法,进而执行p->handler_->handle(p)方法处理Packet;
    4)        上述handle(p)实际执行Phy类的handle(p)方法,最终会调用recv()方法;
    5)        Phy类的recv()方法执行,根据包头中的方向字段,调用sendUp()或者sendDown()方法,此处是从下层Channel接收,因此调用sendUp();
    6) sendUp()方法中再次包含schedule()方法,至此完成一次Packet调度。

    3.   总结
       从以上可以看出,各个协议层功能实体之间的事件(包)传递便是通过Scheduler调度完成的,各层实体之间并不直接调用彼此的方法,这就使得各实体之间的耦合更弱,从而便于各层协议替换和扩展。
  • 相关阅读:
    201521123076《java程序设计》第12周学习总结
    个人作业4——alpha阶段个人总结
    软工网络15个人作业3——案例分析
    软件工程网络15结对编程作业(201521123083)
    软件工程网络15个人阅读作业2-提出问题
    软件工程第一次个人阅读作业
    java课程设计——博客作业教学数据分析系统(201521123083 戴志斌)
    201521123083《Java程序设计》第13周学习总结
    201521123083《Java程序设计》第12周学习总结
    201521123083《Java程序设计》第11周学习总结
  • 原文地址:https://www.cnblogs.com/zhangleiccst/p/2156232.html
Copyright © 2020-2023  润新知