4,初学ns2,我一直有一个困惑,就是ns2的时间到底是怎么模拟的,其实我想无外乎就这么三种方法,一,使用OS的物理时钟;二,同nachos(一个实验用操作系统)一样,执行一条指令系统滴答数加一;三,也是我想ns2最有可能的时间组织方式,通过网络延时来递加时间,因为网络模拟所需要的时间的增加唯一就表现在端对端的延时上了,而ns2的模拟是一种精确模拟(事先设计好各种模拟量,程序运行是不会有偶然事件发生的),并且是事件驱动性的,每一个事件的派发都会引起时间的增加(或者不变),例如事件P1声称会在开始模拟后的15s的时候发生,P2在30s的时候发生,那么只需要将P1和P2安顺序派发并且时间变到30s就可以了;
通过对代码的研究,最后发现还真是验证了我的猜想,呵呵。证据:
在/ns2.33/common/scheduler.cc中
void
Scheduler::schedule(Handler* h, Event* e, double delay)
{
。。。。。
double t = clock_ + delay;
;计算一下时间发生的绝对时间
e->time_ = t;
}
void
Scheduler::dispatch(Event* p, double t)
{
。。。。。
clock_ = t;
;clock_ 就是系统的时间。
。。。。。
}
在这里顺便说一下ns2的schedule,其实可以简单的理解为一个队列(ns2中的实现是一个calendar算法,说是可以使hold(就是一进一出)的时间达到O(1)的复杂度,我只是看了看该论文的引言部分,没有仔细研究,但ns2就是这么实现的,而且该实现是(futrue event set problem)现在比较好的实现了。
这里timer类也是以后开发离不开的一个类了,继承timer了的子类必须实现一个expeir的方法,该方法在事件被派发也就是“时间到”的时候被执行。
这里在举一个例子说明一下timer的使用方法:
snd_timer_.resched(next_time_) //调用一个timer(snd_timer)。
TimerHandler::resched(double delay)
{
if (status_ == TIMER_PENDING)
_cancel();
_sched(delay); //在这里再调用一下timerhander的方法。
status_ = TIMER_PENDING;
}
inline void _sched(double delay) {
(void)Scheduler::instance().schedule(this, &event_, delay);
//这里就调用了上面讲过的scheduler的函数了。
}
通过这个例子能够对ns2的时间系统以及timer的应用有一个更加深入的了解了。
最后说明一点就是 Packet 类也是继承了 event 类的子类,所以也都是通过 scheduler 派发出去的。