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派發出去的。