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部分的一点认识相关推荐

  1. 理解NS2中的OTcl/tclCL

    题记 真正触动我写这篇短文的原因是试图理解NS2的基本原理. 在"the NS2 manual"中, 解释了为什么采用了两种语言来建构整个系统, 然后在第三章描述了tclcl的六个 ...

  2. 向NS2中添加协议PING

    在NS2中增加自己的协议模块一般分一下几个步骤: (1)       添加协议类 (2)       定义协议分组头结构 (3)       编译代码 其实在ns3.35版本中已经有ping协议,此步 ...

  3. 向NS2中添加协议PING[转载]

    原文地址:http://www.cnblogs.com/xyl-share-happy/archive/2012/03/20/2407732.html ------------------------ ...

  4. matlab 中trace,trace命令和tracert命令的用途 matlab中的trace 怎么用的?

    导航:网站首页 > trace命令和tracert命令的用途 matlab中的trace 怎么用的? trace命令和tracert命令的用途 matlab中的trace 怎么用的? 相关问题: ...

  5. mysql 手动写时间_关于数据库中如何存储时间的一点思考

    1.切记不要用字符串存储日期 我记得我在大学的时候就这样干过,而且现在很多对数据库不太了解的新手也会这样干,可见,这种存储日期的方式的优点还是有的,就是简单直白,容易上手. 但是,这是不正确的做法,主 ...

  6. NS2中数据包Packet的分析 (转帖)

    1. NS2中数据包packet类结构图: packet类中的access函数如下: inline unsigned char* access(int off) const {      if (of ...

  7. Golang中WaitGroup使用的一点坑

    Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...

  8. 【ABAP系列】SAP ABAP中关于commit的一点解释

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP中关于commi ...

  9. NS2中的WirelessPhyExt工作机制研究

    NS2中的WirelessPhyExt工作机制研究 @NS2开发笔记 1.概述 WirelessPhyExt是WirelessPhy的扩展,是直接从WirelessPhy继承而来的,但是在Wirele ...

最新文章

  1. 在java项目中加载IEDriverServer.exe引用路径
  2. 计算机启动太慢可以设置什么来加速启动速度,电脑开机速度慢怎么办 如何加速电脑开机速度慢【详细介绍】...
  3. 'React/RCTBridgeDelegate.h' file not found
  4. Error loading MySQLdb module: No module named MySQLdb
  5. matlab 读取fig数据
  6. android studio设置生成的release版本apk的名称
  7. 日常问题———安装新版zookeeper 出现Starting zookeeper ... FAILED TO START
  8. pandas to_sql保存数据到数据库后,添加自增长的主键ID(PRIMARY KEY)
  9. python画拓扑图权值是线条粗细_python—networkx:根据图的权重画图
  10. Javascript 535种方式!!!实现页面重载
  11. perl 语言中的q,qw,qr,qx,qq符号用法总结
  12. 武汉大学计算机考研复试考什么,2018武汉大学计算机考研复试经验贴
  13. 在线坐标系经纬度转换工具
  14. 红米k30s 至尊纪念版本看闪存型号 硬盘型号
  15. 工业控制靶场记录以及工业控制协议的简单介绍
  16. 使用MagicIndicator+ViewPager2出现requestLayout() improperly called by
  17. 上线文件服务器域名怎么建站,怎么做网站?建站详细流程
  18. 计算机网络多项式的定义,多项式的定义与概念
  19. pandas 第十二期组队-pandas基础
  20. Diffusion惊艳应用大赏

热门文章

  1. 我的第一个网站“爱汉服”
  2. 中央电大网考计算机基础试题,电大网考计算机应用基础统考试题
  3. 前端开发者自述:我的第一个iPhone应用是这么诞生的
  4. 幻世(OurDream)2D图形引擎使用教程11——播放媒体文件(1)
  5. Java提高篇(三四)-----fail-fast机制
  6. js父元素获取子元素img_js获得子页面元素
  7. mysql外键约束案例_SQLServer FOREIGN KEY外键约束讲解及使用实例
  8. ubuntu kylin18 安装NVIDIA驱动
  9. [小技巧] Word 使用
  10. web应用常见的攻击手段