NS2中Trace部分的一点认识
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中的OTcl/tclCL
题记 真正触动我写这篇短文的原因是试图理解NS2的基本原理. 在"the NS2 manual"中, 解释了为什么采用了两种语言来建构整个系统, 然后在第三章描述了tclcl的六个 ...
- 向NS2中添加协议PING
在NS2中增加自己的协议模块一般分一下几个步骤: (1) 添加协议类 (2) 定义协议分组头结构 (3) 编译代码 其实在ns3.35版本中已经有ping协议,此步 ...
- 向NS2中添加协议PING[转载]
原文地址:http://www.cnblogs.com/xyl-share-happy/archive/2012/03/20/2407732.html ------------------------ ...
- matlab 中trace,trace命令和tracert命令的用途 matlab中的trace 怎么用的?
导航:网站首页 > trace命令和tracert命令的用途 matlab中的trace 怎么用的? trace命令和tracert命令的用途 matlab中的trace 怎么用的? 相关问题: ...
- mysql 手动写时间_关于数据库中如何存储时间的一点思考
1.切记不要用字符串存储日期 我记得我在大学的时候就这样干过,而且现在很多对数据库不太了解的新手也会这样干,可见,这种存储日期的方式的优点还是有的,就是简单直白,容易上手. 但是,这是不正确的做法,主 ...
- NS2中数据包Packet的分析 (转帖)
1. NS2中数据包packet类结构图: packet类中的access函数如下: inline unsigned char* access(int off) const { if (of ...
- Golang中WaitGroup使用的一点坑
Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...
- 【ABAP系列】SAP ABAP中关于commit的一点解释
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP中关于commi ...
- NS2中的WirelessPhyExt工作机制研究
NS2中的WirelessPhyExt工作机制研究 @NS2开发笔记 1.概述 WirelessPhyExt是WirelessPhy的扩展,是直接从WirelessPhy继承而来的,但是在Wirele ...
最新文章
- 在java项目中加载IEDriverServer.exe引用路径
- 计算机启动太慢可以设置什么来加速启动速度,电脑开机速度慢怎么办 如何加速电脑开机速度慢【详细介绍】...
- 'React/RCTBridgeDelegate.h' file not found
- Error loading MySQLdb module: No module named MySQLdb
- matlab 读取fig数据
- android studio设置生成的release版本apk的名称
- 日常问题———安装新版zookeeper 出现Starting zookeeper ... FAILED TO START
- pandas to_sql保存数据到数据库后,添加自增长的主键ID(PRIMARY KEY)
- python画拓扑图权值是线条粗细_python—networkx:根据图的权重画图
- Javascript 535种方式!!!实现页面重载
- perl 语言中的q,qw,qr,qx,qq符号用法总结
- 武汉大学计算机考研复试考什么,2018武汉大学计算机考研复试经验贴
- 在线坐标系经纬度转换工具
- 红米k30s 至尊纪念版本看闪存型号 硬盘型号
- 工业控制靶场记录以及工业控制协议的简单介绍
- 使用MagicIndicator+ViewPager2出现requestLayout() improperly called by
- 上线文件服务器域名怎么建站,怎么做网站?建站详细流程
- 计算机网络多项式的定义,多项式的定义与概念
- pandas 第十二期组队-pandas基础
- Diffusion惊艳应用大赏
热门文章
- 我的第一个网站“爱汉服”
- 中央电大网考计算机基础试题,电大网考计算机应用基础统考试题
- 前端开发者自述:我的第一个iPhone应用是这么诞生的
- 幻世(OurDream)2D图形引擎使用教程11——播放媒体文件(1)
- Java提高篇(三四)-----fail-fast机制
- js父元素获取子元素img_js获得子页面元素
- mysql外键约束案例_SQLServer FOREIGN KEY外键约束讲解及使用实例
- ubuntu kylin18 安装NVIDIA驱动
- [小技巧] Word 使用
- web应用常见的攻击手段