一. Mac802_11定时器相关类介绍

类图如下:

http://120.img.pp.sohu.com/images/blog/2007/12/3/16/16/1173b4c9ccf.jpg

图1 NS2中Mac802_11定时器相关类结构图

PS:在~ns\Common\Timer-handler.[h,cc]中定义了一个TimerHandler类,该类是ns中的通用定时器,不过MAC中并未使用它,而是自行定义一些功能和机制与其相似的timer。

重要类介绍(以下类定义位置均在 ~ns\Mac\Mac-timers.[h,cc]):

1. MacTimer : Handler

作用概述:

1)Mac802_11中timer的共同父类;   

2)派生自Handler类,因此定时器就可以作为Scheduler::schedule(Handler*, Event*, double delay)方法中的Handler*参数传递给事件调度器,从而作为超时后的事件处理器。

重要属性/方法:

1) protected Mac802_11 *mac;

    用于timer调用mac的对应超时处理方法,timer的构造函数以Mac802_11类实例的指针为参数,并将其赋值给mac。

2) public virtual void start(double time)
    {
       ...  //设置timer状态,记录时间

       s.schedule(this, &intr, rtime);  

       //this为timer自己的引用;rtime为timer的计时时长;&intr为Event类型,用于标记此定时器事件   }

    start()最终调用schedule(),使事件调度器在经过rtime时间之后通知timer处理超时,以此实现了定时和超时通知的,即定时器的能力实际是由基于时间的事件调度器来实现的。

3) public virtual void stop()

    主要调用了Scheduler::cancel(&intr)方法,取消调度器中的该定时器事件,并重置timer状态。

4) public inline double expire()
     {
        return ((stime + rtime) - Scheduler::instance().clock());
     }

    区别于NS的通用定时器TimerHandler::expire(),此方法仅用于返回距离定时器超时还有多久时间。

2. BackoffTimer : MacTimer

作用概述(结合IEEE802.11中的描述,参见图1.2):

mac定时执行python脚本 mac定时器_random

图1.2 IEEE802.11定时机制示意图

1) 用于竞争退避机制:在检测到介质持续空闲了一个DIFS(DCF InterFrame Space)或EIFS(Extended InterFrame Space)时长后,如果此时站点STA的回退计时器backoff timer为零,则STA将产生一个随机回退时间而不是立即接入,从而减少多个等待的STA在DIFS后同时接入而产生冲突;不为零时则继续按照回退计时器内容等待。

2) Backoff Time = Random() × aSlotTime;

3) Random()——返回[0,CW]之间的一个随机整数,CW为当前竞争窗口大小;

4) 在DIFS或EIFS结束后STA继续检测介质,每检测完一个空闲aSlotTime时长回退计时器就减一;若在回退计时器还在计时工作的期间检测到介质忙,则暂停回退计时器,待介质重新空闲且持续DIFS或EIFS后,回退计时器才继续。

5) 回退计时器减为零时,立即开始信道占用。

重要属性/方法:

1) public void handle(Event *e)
    {        ...  // 重置timer状态
       mac->backoffHandler() // 调用Mac802_11对应超时处理方法
   }

   BackoffTimer超时的处理方法,将真正的backoff超时处理交给Mac802_11完成。

2) public void start(int cw, int idle)
    {       ...
       rtime = (Random::random() % cw) * mac->phymib_.getSlotTime();  // 生成随机回退时间      ...
       if(idle == 0)
           paused_ = 1;  // 当前信道不空闲,则暂停BackoffTimer,实际最终会触发pause()方法      else {
           assert(rtime >= 0.0);          s.schedule(this, &intr, rtime);  // 信道为空闲,开始回退计时
      } 
    }

  该方法即可用于启动新的回退计时,也可用于“暂停”当前回退计时。

3) public void pause()
    {
       ... // 计算剩余回退时隙数slots      rtime -= (slots * mac->phymib_.getSlotTime());  // 修改超时时间
      s.cancel(&intr);  //取消调度器中的该定时事件,从而达到暂停计时的目的
   }

  该方法为暂停BackoffTimer所做的实际操作。

4) public void resume(double difs)
    {
      ...     difs_wait = difs;  // 重置difs间隔时长
     s.schedule(this, &intr, rtime + difs_wait);  // 恢复回退计时
   }

  该方法用于重置difs间隔并恢复BackoffTimer的计时;

3. DeferTimer : MacTimer

作用概述(结合IEEE802.11中的描述,参见图1.2):

1) 用于表示接入信道需要延迟的时间(不包括回退时间)

2) 当STA监听信道时正确接收到了RTS/CTS等信息时,会得知当前信道将被占用的时长,该时长加上DIFS或EIFS时长即为需要延迟接入的时间defer time。

4. NavTimer : MacTimer

作用概述(结合IEEE802.11中的描述,参见图1.2):

1) Nav是一个由每个基站各自维护的指示器,它指示基站不能在无线介质上发起传输的时间段,无论基站是否检测到介质忙;

2) MAC采用的是虚拟载波监听(区别于物理层的物理载波监听),因此需要NAV以及物理载波监听结果来联合决定介质的空闲与否;

3) NAV就像一个以恒定速率递减的计数器,当计数器不为零时,虚拟载波监听认为介质忙,为零时认为空闲。

4) STA通过接收其它STA发送的帧里的Duration/ID域来更新NAV——当该值大于当前STA的NAV值且该帧不是发给这个STA的时候,就以新的值设置NAV。

5) NAV用于实现虚拟载波监听,它关注介质的忙状态(它在介质忙的时候递减);而backoff timer用于实现回退机制以减少冲突,它关注介质的空闲状态(它在介质空闲的时候递减)。
 

5. RxTimer : MacTimer

作用概述:

1) Mac802_11定义的定时器,用于模拟接收一个完整分组所花的接收时延;

2) 在接收分组时启动,Mac802_11进入MAC_RECV状态,在定时器超时前若又有其它分组到来则会改变mac状态;在定时器超时后检查mac状态即可得知分组是否正确接收完。

6. TxTimer : MacTimer

作用概述:

1) 发送方发出一个消息后需要得到相应回复,如CTS/ACK等;该定时器即被发送方用于对回复信息的计时;

2) 在Mac802_11::transmit()方法中启动,定时器超时后表示在规定时间内没有收到回复,调用Mac802_11::sendHandler(),进而调用Mac802_11::send_timer(),根据发送状态判断是否需要重传以及重传何种类型的消息(RTS/CTS/DATA/ACK)。

7. IFTimer : MacTimer

作用概述:

1) Mac802_11定义的定时器,用于模拟发送一个完整分组所花的发送时延;

2) 在Mac802_11::transmit()方法中启动,定时器超时后表示分组已经发送成功,调用Mac802_11::txHandler(),其中调用mac层trace对象EOTtarget_->recv(eotPacket_, (Handler *) 0),并设置mac的发送状态tx_active_为0。

上述3至7号timer的属性/方法较简单且相似,统一介绍如下:

1)public void handle(Event *e)
   {      ...  // 重置timer状态
     mac->XXXHandler()  // 调用Mac802_11对应超时处理方法,XXX通常为timer名称
  }

  XXXTimer超时的处理方法,将实际的超时处理交给Mac802_11:: XXXHandler()方法完成。

二. 总结

NS中定时器工作机制总结如下:

1. 先通过定时器的start(time)方法,向Scheduler中加入延迟为time的事件,事件的处理器为Timer自己;

2. 延迟time时间之后,Scheduler调度Timer的handle()方法,表示定时器超时,进而实现定时器超时处理;

3. 超时前可以调用Timer的stop方法,进而调用Scheduler::cancel(e)方法,取消定时器计时事件。