NS2中Trace部分的一点认识
来源:互联网 发布:如何用mac剪辑音频 编辑:程序博客网 时间:2024/06/02 02:28
NS2中Trace部分的一点认识
NS2追踪部分的源码主要涉及以下几个文件:
ns-2.34/trace/basetrace[.cc][.h]
ns-2.34/trace/trace[.cc][.h]
ns-2.34/trace/cmu-trace[.cc][.h]
ns-2.34/tcl/lib/ns-lib.tcl
ns-2.34/tcl/lib/ns-mobilenode.tcl
仿真输出文件如何与 OTcl 解释层次关联
以标准的仿真脚本文件 ns-2.34/tcl/ex/simple.tcl 为例,在开头部分有如下定义:
set f [open out.tr w]
$ns trace-all $f
第一句的作用是创建并且以只写的方式打开了追踪文件out.tr,第二句则调用了trace-all 这个 tcl 函数将创建的文件的操作句柄传递 tcl 变量。其原型如下(ns/tcl/lib/ns-lib.tcl):
Simulator instproc trace-all file {
$self instvar traceAllFile_
set traceAllFile_ $file
}
由此可知,在 OTcl 类 Simulator 中增加一个成员 traceAllFile_,并将追踪文件的句柄赋值给它。通过这个操作,追踪文件便被传递到解释层次中,可供随时调用。traceAllFile_ 这个成员变量比较重要,后面还会用到。
编译层次C++下的trace函数如何实现追踪数据:
通过阅读 ns-2.34/trace/ 下的 .cc 和 .h 代码,由函数的调用关系大概可以猜测到当我们在追踪 packet 的时候,应该是系统在某个地方调用了类class Trace 的 recv 函数,而 recv 继而会调用 format 函数去整理输出信息。在 format 函数中,有效信息都被输入到 pt_->buffer() 中了,在这里可能会产生疑问,我们最终看到的结果都是在输出文件 out.tr 中,在这怎么都输出到 pt_ 中了?查一下 pt_ 发现是类 class Trace 在构造的时候创建的 pt_ = new BaseTrace; 原来这个 pt_ 是一个由类 class BaseTrace 产生的对象。
Trace 又是怎样和输出文件 out.tr 关联起来的呢?
前面已经提到 out.tr 和解释层次 OTcl 中的成员变量 traceAllFile_ 关联起来了,那我们可以猜测 traceAllFile_ 应该是和 BaseTrace 在某个地方被关联起来了。而最有可能就是在创建节点的时候。
脚本中调用 set n0 [$ns node] 创建节点的过程我就不细说了。在ns-2.34/tcl/lib/ns-lib.tcl 中我们找到
Simulator instproc create-wireless-node 函数,中发现创建节点的时候有这样的操作:
set tracefd [$self get-ns-traceall]
if {$tracefd != "" } {
$node nodetrace $tracefd
$node agenttrace $tracefd
}
set namtracefd [$self get-nam-traceall]
if {$namtracefd != "" } {
$node namattach $namtracefd
}
第一句中又调用了 get-ns-traceall 这个函数,看一下它的原型只可它返回的就是 traceAllFile_。思路开始渐渐清晰,$node nodetrace $tracefd 调用了 nodetrace 这个函数,并将 $tracefd 也就是 traceAllFile_ 作为参数传递过去。在 ns/tcl/lib/ns-mobilenode.tcl 中,定义如下:
Node/MobileNode instproc nodetrace { tracefd } {
#
# This Trace Target is used to log changes in direction
# and velocity for the mobile node.
#
set T [new Trace/Generic]
$T target [[Simulator instance] set nullAgent_]
$T attach $tracefd
$T set src_ [$self id]
$self log-target $T
}
到此我们豁然开朗,在这函数中,创建了一个新的 Trace/Generic 对象,并通过 $T attach $tracefd 将这个新的对象链接到 traceAllFile_ 上,也就是链接到了输出文件 out.tr 上。
最后一句 $self log-target $T,这里 $self 指的是 Node/MobileNode 我们查看编译层次中类 class MobileNode 的 command 函数(ns-2.34/common/mobilenode[.cc][.h])会发现 log-target 这个操作的原型:
else if(strcmp(argv[1], "log-target") == 0) {
log_target_ = (Trace*) TclObject::lookup(argv[2]);
if (log_target_ == 0)
return TCL_ERROR;
return TCL_OK;
}
log_target_ 是在类 class MobileNode 中定义的 Trace* log_target_;
现在我们终于明白了NS2追踪功能的链接过程,在编译层次中声明一个类 class Trace的指针 log_target_ (通常叫这个名字),然后在解释层次中生成一个新的 Trace 对象,并将它们链接起来。
这部分遗留了一个问题:生成的新的 Trace/Generic 对象从其写法上看应该是从类 Trace 派生出来的一个子类。但是在 ns-2.34/trace/ 文件夹下却没找到它的声明,迷茫中。
链接的过程我们大概已经有了一点认识,贯穿起来想一下,追踪功能是怎么实现的?
无线仿真的脚本中,通常在 $ns_ node-config 的时候会传递一堆参数进去,其中就有追踪功能的开关,我们仅以 -macTrace ON 为例。逐步分析一下。
首先我们在ns/tcl/lib/ns-lib.tcl中找到 Simulator instproc node-config 这个函数,并且在其中找到如下的定义:
if [info exists macTrace_] {
Simulator set MacTrace_ $macTrace_
}
if [info exists routerTrace_] {
Simulator set RouterTrace_ $routerTrace_
}
if [info exists agentTrace_] {
Simulator set AgentTrace_ $agentTrace_
}
由此可以看出,传递进来的变量macTrace_被赋值给MacTrace_,那么也就是说MacTrace_ 就是那个开关。我们继续搜索 MacTrace_ 这个变量,发现它在 ns/tcl/lib/ns-mobilenode.tcl 中的 Node/MobileNode instproc add-interface 函数出现过。源码如下:
if { [Simulator set MacTrace_] == "ON" } {
#
# Trace RTS/CTS/ACK Packets
#
if {$imepflag != ""} {
set rcvT [$self mobility-trace Recv "MAC"]
} else {
set rcvT [cmu-trace Recv "MAC" $self]
}
$mac log-target $rcvT
if { $namfp != "" } {
$rcvT namattach $namfp
}
#
# Trace Sent Packets
#
if {$imepflag != ""} {
set sndT [$self mobility-trace Send "MAC"]
} else {
set sndT [cmu-trace Send "MAC" $self]
}
$sndT target [$mac down-target]
$mac down-target $sndT
if { $namfp != "" } {
$sndT namattach $namfp
}
#
# Trace Received Packets
#
if {$imepflag != ""} {
set rcvT [$self mobility-trace Recv "MAC"]
} else {
set rcvT [cmu-trace Recv "MAC" $self]
}
$rcvT target [$mac up-target]
$mac up-target $rcvT
if { $namfp != "" } {
$rcvT namattach $namfp
}
#
# Trace Dropped Packets
#
if {$imepflag != ""} {
set drpT [$self mobility-trace Drop "MAC"]
} else {
set drpT [cmu-trace Drop "MAC" $self]
}
$mac drop-target $drpT
if { $namfp != "" } {
$drpT namattach $namfp
}
} else {
$mac log-target [$ns set nullAgent_]
$mac drop-target [$ns set nullAgent_]
}
越来越接近问题所在,我们取出最开始的一段代码分析,
if {$imepflag != ""} {
set rcvT [$self mobility-trace Recv "MAC"]
} else {
set rcvT [cmu-trace Recv "MAC" $self]
}
$mac log-target $rcvT
先不管 imepflag 是干嘛的(实际上在 Simulator instproc create-wireless-node 的开头已经被屏蔽),
注意 set rcvT [$self mobility-trace Recv "MAC"] 函数,在ns/tcl/lib/ns-mobilenode.tcl 可以找到 Node/MobileNode instproc mobility-trace 的定义:
Node/MobileNode instproc mobility-trace { ttype atype } {
set ns [Simulator instance]
set tracefd [$ns get-ns-traceall]
if { $tracefd == "" } {
puts "Warning: You have not defined you tracefile yet!"
puts "Please use trace-all command to define it."
return ""
}
set T [new CMUTrace/$ttype $atype]
$T newtrace [Simulator set WirelessNewTrace_]
$T tagged [Simulator set TaggedTrace_]
$T target [$ns nullagent]
$T attach $tracefd
$T set src_ [$self id]
$T node $self
return $T
}
这也是在解释层次创建一个新的 Trace 对象,并完成到 out.tr 的链接。最后一句 $mac log-target $rcvT 就是调用 command 将编译层次声明的指针与解释层次生成的对象连接。
链接完成如何使用?在类 class Mac 中有这样的定义:
private:
void mac_log(Packet *p) {
logtarget_->recv(p, (Handler*) 0);
}
NsObject* logtarget_;
注意这里并没有将 logtarget_ 声明为 Trace*,但是查看追踪的基类 class Trace 你会发现 Trace 就是从 NsObject 继承来的,因此 logtarget_就是在 command 中被链接的指针。
而函数void mac_log(Packet *p){
logtarget_->recv(p, (Handler*)0);
}
就是调用 Trace 的 recv,继而调用 format 记录有效信息。
剩下的工作我们通篇搜索函数mac_log的出现,容易发现有3个地方,在ns-2.34/mac/mac-802_11.cc中,参考其应用即可。
最后有个细节需要注意,基类中的声明:
private:
void mac_log(Packet *p) {
logtarget_->recv(p, (Handler*) 0);
}
NsObject* logtarget_;
是 private,如果你要实现自己的追踪,必须在你新建的类中重新声明这个变量和函数,并且在 command 中实现链接。
- NS2中Trace部分的一点认识
- ns2中限制Trace文件的输出
- ns2中限制Trace文件的输出
- ns2中限制Trace文件的输出
- NS2中trace分析工具
- ns2中关于mac层802.11协议的学习“trace”
- NS2 trace
- NS2 trace
- NS2中trace文件格式分析1_新trace格式
- NS2中trace文件格式分析2_旧trace格式
- NS2无线仿真的trace格式
- NS2下的无线Trace文件分析
- ns2的trace文件分析过程
- NS2:能量模型以及新版Trace格式仿真结果(.tr文件)中各数据的含义
- 对于php中magic_quotes_gpc的一点认识
- Linux中configure命令的一点认识
- NS2中有线网络trace文件分析脚本(awk)
- NS2中无线trace分析(第1课)
- Android4.0 input事件输入流程详解(中间层到应用层)
- Python进制转换(二进制、十进制和十六进制)
- 关于elf的一些记录
- hdu 1712 分组背包
- 一个程序员创业的经历
- NS2中Trace部分的一点认识
- 解决Tomcat 不能下载带中文文件名的附件的方法
- 傅丽叶变换(二)
- android样式学习(一) 使用selector改变来动态改变背景颜色
- 代码实现Lable 、textField创建界面以及键盘的处理
- eclipse反编译插件jadclipse
- 反编译工具jad的使用
- Google App Engine Launcher无法启动问题解决
- 设计模式3 - 单例模式Singleton