【NS2】NS2机制浅显分析一下(转载)
[我在之前看的是以ping协议为实例来理解TclCL机制和分裂对象模型]
本文以channel实例的创建过程为例,试图说明ns2的分裂机制,请在阅读本文前阅读《The NS Manual》有关分裂机制章节,由于篇幅有限,作者能力有限,本文章不能分析得非常彻底,时间仓促,有不当之处请大家给予批评指正。
一、定义信道基类
定义channel的 C++类
#ns-2.31macchannel.h
class Channel : public TclObject {
public:
Channel(void);
virtual int command(int argc, const char*const* argv);
... ... ...
};
定义用于连接的类
#ns-2.31macchannel.cc
static class ChannelClass : public TclClass {
public:
ChannelClass() : TclClass("Channel") {}
TclObject* create(int, const char*const*) {
return (new Channel);
}
}class_channel ;
[注意]一个类声明为static,那么当ns刚开始初始化的时候,便会调用该类的构造函数,当静态变量class_channel 第一次被创建时,ns 将执行其构造函数,这就建立了适当的方法和解释类层次.具体解释请看第三节Otcl注册过程
二、Otcl注册过程
继续第一节,当ns初始化时会创建实体class_channel,它会调用类的构造函数ChannelClass() : TclClass("Channel") {}
首先执行TclClass:TclClass("Channel"),"Channel" 会传给参数此classname_ .
下面我们看一下TclClass()的具体实现
//->tclcl-1.19Tcl.cc
TclClass* TclClass::all_; //[problem]什么意思? 在c++里
TclClass::TclClass(const char* classname) : class_(0), classname_(classname)
{
if (Tcl::instance().interp()!=NULL) {
#解释器已经存在,解释器是一个动态连接库的一部分
bind(); # 变量绑定函数
} else {
... ... ...
}
}
void TclClass::bind()
{
Tcl& tcl = Tcl::instance();
//获取Tcl 句柄 [参考1]
tcl.evalf("SplitObject register %s", classname_); # $classname_ == "Channel"
//上句利用句柄调用otcl命令,在Otcl环境中注册该类名:Channel
该类的父类是SpliteObject
//SpliteObject是一个具有C++映像类的OTcl类,他是所有OTcl映像类的基类
# 注册了之后,为这个类添加两个命令:create-shadow和delete-shadow
# 调用命令就是TclClass::create_shadow(),TclClass::delete_shadow().
class_ = OTclGetClass(tcl.interp(), (char*)classname_);
//class_
OTclAddIMethod(class_, "create-shadow",
(Tcl_CmdProc *) create_shadow, (ClientData)this, 0);
OTclAddIMethod(class_, "delete-shadow",
(Tcl_CmdProc *) delete_shadow, (ClientData)this, 0);
otcl_mappings();
}
下边来讲讲我们在tcl脚本里自己能控制的实例化过程
四、实例化过程
然后当你在tcl 脚本中调用 new Channel时,ns2使用tclsh解释执行tcl脚本, 调用tcl函数new函数
//tclcl-1.19/tcl-object.tcl
146 proc new { className args } {
set o [SplitObject getid]
#得到一个新的分裂实体编号"_o*" _o*有类SplitObject 的变量 id 标识,从_o0开始
#可见在每一个Simulator对应的模拟中"_o*"标示唯一的一个分裂类实体,
#也就是说,所有的分裂类实体都有自己的唯一标识 ,这个标识就是句柄
#注意SplitObject 与 TclObject 的关系
if [catch "$className create $o $args" msg] { #创建实体
if [string match "__FAILED_SHADOW_OBJECT_" $msg] {
# 如果创建影像类失败,删除 o对象
delete $o
return ""
}
global errorInfo
error "class $className: constructor failed: $msg" $errorInfo
}
return $o
}
但是SpliteObject并没有create函数, 所以动态调用其父类 Class 的 create 函数
Class instproc create {obj args} { # obj是 _oxxx了
set h [$self info heritage] # 取得类继承链测试结果是“SplitObject Object”
foreach i [concat $self $h] {
#沿着继承链从子类到父类递归产生相应实体
#concat后字符串为:”Channel SplitObject Object”
if {[$i info commands alloc] != {}} then { # 判断命令alloc的是否存在
set args [eval [list $i] alloc [list $obj] $args] # 分配空间
$obj class $self
eval [list $obj] init $args #调用init,最终导致shadow对象的产生
return $obj
}
}
error {No reachable alloc}
}
上面调用的init 会动态调用 SpliteObject instproc init()
SplitObject instproc init args {
$self next
#调用类的create-shadow函数
if [catch "$self create-shadow $args"] {
error "__FAILED_SHADOW_OBJECT_" ""
}
}
在这个例子中,动态调用了Channel instproc create_shadow函数,channel没有次函数,调用父类的,实质上最后调用了TclClass::create-shadow()函数,创建
int TclClass::create_shadow(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
{
TclClass* p = (TclClass*)clientData; #把channel指针转换为父类型的指针
#在这里调用了ChannelClass::create()函数
#也就是调用了C++环境中的:new Channel 见函类ChannelClass定义
#到这里为止,otcl中的Channel的shadow object就生成了
TclObject* o = p->create(argc, argv);
#动态调用那个create?
Tcl& tcl = Tcl::instance();
if (o != 0) {
o->name(argv[0]);
tcl.enter(o);
if (o->init(argc - 2, argv + 2) == TCL_ERROR) {
tcl.remove(o);
delete o;
return (TCL_ERROR);
}
tcl.result(o->name());
# 在这里再次为otcl中的类Channel添加两个instproc:cmd和instvar
# 其中cmd命令是用来运行处理未知命令机制的
# 这样的话,当你在ns脚本中输入了一个该类未知的命令,
# Tcl的unknown机制就会调用该类的cmd命令
# 而这进一步的就会调用该类的shadow object的command()过程
# 所以在实现类的C++部分时,你必须实现该类的Command()过程
# 在command()中实现所有的命令分发
OTclAddPMethod(OTclGetObject(interp, argv[0]), "cmd",
dispatch_cmd, (ClientData)o, 0);
OTclAddPMethod(OTclGetObject(interp, argv[0]), "instvar",
dispatch_instvar, (ClientData)o, 0);
o->delay_bind_init_all();
return (TCL_OK);
} else {
tcl.resultf("new failed while creating object of class %s",
p->classname_);
return (TCL_ERROR);
}
}
【NS2】NS2机制浅显分析一下(转载)的更多相关文章
- Java虚拟机类加载机制——案例分析
转载: Java虚拟机类加载机制--案例分析 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...
- Redis 发布/订阅机制原理分析
Redis 通过 PUBLISH. SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能. 这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播.实时 ...
- Android 中View的绘制机制源代码分析 三
到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...
- Android AdapterView 源码分析以及其相关回收机制的分析
忽然,发现,网上的公开资料都是教你怎么继承一个baseadapter,然后重写那几个方法,再调用相关view的 setAdpater()方法, 接着,你的item 就显示在手机屏幕上了.很少有人关注a ...
- 10.hibernate缓存机制详细分析(转自xiaoluo501395377)
hibernate缓存机制详细分析 在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别).二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论 ...
- Netfilter之连接跟踪实现机制初步分析
Netfilter之连接跟踪实现机制初步分析 原文: http://blog.chinaunix.net/uid-22227409-id-2656910.html 什么是连接跟踪 连接跟踪(CONNT ...
- 阿里系产品Xposed Hook检测机制原理分析
阿里系产品Xposed Hook检测机制原理分析 导语: 在逆向分析android App过程中,我们时常用的用的Java层hook框架就是Xposed Hook框架了.一些应用程序厂商为了保护自家a ...
- Android 中View的绘制机制源代码分析 一
尊重原创: http://blog.csdn.net/yuanzeyao/article/details/46765113 差点儿相同半年没有写博客了,一是由于工作比較忙,二是认为没有什么内容值得写, ...
- Android 中View的绘制机制源代码分析 二
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/46842891 本篇文章接着上篇文章的内容来继续讨论View的绘制机制,上篇文章中我们主要解说 ...
随机推荐
- Web前端浏览器兼容性个人经验总结
前言 浏览器兼容是前端开发人员必须掌握的一个技能,但是初入前端的同学或者其他后台web开发同学往往容易选择忽略,而形成两个极端: 我最开始都是使用IE6,IE6上没问题,其它浏览器坑爹(多出现与前端后 ...
- 【python之路26】字符串之格式化%和format
Python基础之杂货铺 字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式, ...
- TZ_05_Spring_转账事务基于xml的开发
事务:通过接口的动态代理加强AccountService 实现转账的事务 ApplicationContext.xml <?xml version="1.0" encodin ...
- ios那些事之如何在ios5上运行gdb
为啥要在ios上运行gdb? 这个问题见仁见智喽.对于搞开发的同学们来所, 有了gdb更方便跟踪分析别人的程序,取长补短:)这里不是教大家crack:) 运行环境: Mac OS 10.7.4 Xco ...
- 读书笔记--Head First Networking目录
1.解决物理网络 2.规划网络布局 3.工具和故障排除 4.包分析 5.网络设备和流量 6.连接网络的路由器 7.路由协议 8.域名系统 9.监控和故障排除 10.无线网络 11.网络安全 12.网络 ...
- vue打包之部署在非根路径下的三两事
首先,感叹一下,2019年已经过去一半,想想自己做了些什么,好像也没做什么. 今天试着配一个nginx,以前的nginx都是指向的/根路径,今天的nginx指向的非/根路径,遇到许多问题的,总结总结. ...
- Breakpoint 断点只生效一次
- 洛谷P1052 过河
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上. 由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青 ...
- NOIP2016参赛日志+总结
这个故事告诉我们,成绩出来之前一定要装弱.这些文字是作者拿到程序后测了洛谷民间数据后写的. 2016.11.18 Day 0 早上五点半起床,洗漱完毕,吃了早饭,收拾收拾,七点半从家出发,去了 ...
- Faster RCNN算法训练代码解析(1)
这周看完faster-rcnn后,应该对其源码进行一个解析,以便后面的使用. 那首先直接先主函数出发py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py ...