欢迎来到专业的唐家秘书网平台! 工作总结 工作计划 心得体会 思想汇报 发言稿 申请书 述职报告 自查报告
当前位置:首页 > 专题范文 > 公文范文 > 正文

ONE相关知识整理之二——仿真前初始化(2022年)

时间:2022-07-12 12:55:03 来源:网友投稿

下面是小编为大家整理的ONE相关知识整理之二——仿真前初始化(2022年),供大家参考。

ONE相关知识整理之二——仿真前初始化(2022年)

 

 ONE 相关知识整理 之 二 —— 仿真前的初始化

 仿真实验前的初始化是整个仿真过程中十分关键的一步,它将创建仿真中使用到的节点以及其上的所有“附加物”,如运动模型、路由等,本文将简要介绍 ONE仿真过程中的整个初始化过程。

 1、 、 宏观 视角—— 方法 的调用顺序 1.1、读入配置 Core 包下的 DTNSim 是整个 ONE 仿真的主类,它定义了 Main 方法作为整个程序的开始点,在仿真开始前,DTNSim 首先从命令行输入的 args 中取得仿真配置文件的名称,并将配置文件载入到 Setting 对象中,以便后续创建节点、运动模型、路由等过程时读取,这里需要注意的是,无论是否在命令行中有给出配置文件的参数,只要默认配置(default_)存在,它就一定会被读取并写入 Setting对象,而命令行中给出的配置文件仅仅是“覆盖”了默认配置,所以,当仿真实验出现了一些与配置文件相异的情况时,首先要想到是否是因为 default_settings 中部分参数的影响,所以建议直接删掉这个文件,以免影响最终实验结果。

 1.2、启动 UI 在读取完数据后,ONE 会根据用户在命令行给出的指令,选择命令行 UI 或图形化 UI 界面对象进行创建,并调用其中的 start()方法,该方法在命令行 UI 和图形化UI的基类DTNSimUI 中实现,分别调用了两个方法,initModel()和runSim(),其中 initModel()由该基类进行实现,完成仿真的初始化过程,runSim()在基类中public static void init(String propFile) throws SettingsError {

  String outFile;

  try {

 //先读入default setting

 if (new File(DEF_SETTINGS_FILE).exists()) {

  //内部机制是直接通过Properties来读的

  Properties defProperties = new Properties();

  (new FileInputStream(DEF_SETTINGS_FILE));

  props = new Properties(defProperties);

 }

 被声明为 abstract,根据 UI 的不同,采用不同的实现。

 1.3、模型初始化 initModel 行的初始化过程主要分成三步,首先是创建了新的 Settings 对象用以读取刚才由 DTNSim 读入的配置项,随后,调用 SimScenario 的 getInstance 方法获取到当前仿真场景对象,getInstance 方法是 Singleton 思想的体现,在进行调用时,它会检查当前是否已有仿真场景存在,若有,返回该场景,若无,则创建一个新场景。这一过程保证了单次仿真过程中不会有多个 SimScenario 出现。

 创建场景的过程即是模型初始化中最重要的一步,它包含了仿真节点的创建(调用 enario 中的 createHosts 方法)与仿真世界(World)的创建(调用对象的参数构造器),前者即是网络中进行通信的节点,是仿真的主体,而后者则负责承载所有节点,当仿真时间线向前推进时,负责调用 update 方法来更新各个节点的状态(移动模型),以及消息(路由)。

 当场景创建完毕后,UI 对象会根据 Settings 中定义的 Report 的名称,调用createObject 方法来创建相应的 Report,这一过程是通过 java 的反射机制完成的,该过程是 java 反射机制非常经典的用例(ngs 类 loadObject 方法),通过类名动态找到相应的类文件,调用相应的构造器来创建对象,非常值得研究,因为在平时的学习、开发过程中,很少会直接接触反射(几乎都由 Spring 这样的框架来完成了反射的工作),故,建议详细阅读这部分代码(较长,此处不贴),深入了解Java 中反射的相关机制。

 public static SimScenario getInstance() {

  if (myinstance == null) {

 myinstance = new SimScenario();

  }

  return myinstance;

 }

 最后,若在配置文件中定义了移动模型的“预热时间”S,那么 UI 对象将会将仿真时钟 SimClock 回拨 S,并进行移动模型的预热,该过程即让节点根据其移动模型,先进行 S 时间的运动,再开始消息传递。

 至此,场景的初始化全部完成。

 2、 微观的小坑——节点的创建的细节 SimScenario 中节点创建的过程因为有特殊性,所以值得详细解读。

 在 createHost 方法中,节点按照 group 来进行创建,也就是说,同一个 group中的节点的对象是“几乎一样”的,它们拥有完全相同的移动模型、路由模型、网卡和 Application。

 对于每一个 group,为了减小创建对象时的开销,ONE 并不是对于每个节点都去创建相应的移动模型、路由模型、网卡和 Application,而是先读取配置项,创建出它们的原型(Prototype)(该过程亦是通过反射完成的),然后在创建各个节点时,各个节点通过调用移动、路由、网卡、Application 类的 replicate 方法,“复制”出一个对象出来,这样减小了直接去构造整个对象的开销,但同时也带来了坑——这一过程调用的是 拷贝 构造器(即形如 Type(Type t)的方法),而不是参数构造器来创造新对象,如下 MapBasedMovement 的 replicate 方法所示

 double warmupTime = 0;

 //如果移动模型有“预热时间”,那么把模拟器的时钟回拨,以实现预热效果

 if (ins(MM_WARMUP_S)) {

  warmupTime = uble(MM_WARMUP_S);

  if (warmupTime > 0) {

 SimClock c = stance();

 c.setTime(-warmupTime);

  }

 } //world对象在场景被创建时,即在构造器中创建了

 = .getWorld(); //移动模型的预热 pMovementModel(warmupTime);

 当实现自己的移动模型和路由模型时,要特别注意这一点,如果要让这些模型在不同的节点上有不同表现,必须在 拷贝 构造器中有所体现,而不能只在参数构造器中做操作,因为参数构造器仅在创建那个“Prototype”的时候被调用一次!

 public MapBasedMovement replicate() {

  return new MapBasedMovement(this);

 }

推荐访问:ONE相关知识整理之二——仿真前初始化 之二 初始化 相关知识