OPNET学习入门指南.docx
- 文档编号:24127275
- 上传时间:2023-05-24
- 格式:DOCX
- 页数:10
- 大小:23.29KB
OPNET学习入门指南.docx
《OPNET学习入门指南.docx》由会员分享,可在线阅读,更多相关《OPNET学习入门指南.docx(10页珍藏版)》请在冰豆网上搜索。
OPNET学习入门指南
OPNET学习入门指南
1.预备知识
这部分给大家介绍一下在加入课题组之后,和正式的投入课题开展工作之前大家需要具备的一些基本的背景知识。
这些知识都是在大家以后的课题中或多或少,或明或暗的需要使用到的,打下一个扎实的理论基础对后面工作的开展有极大的好处,这个大家往后一定能够体会到。
正所谓“磨刀不误砍柴工”,大家应该抓住这段宝贵的时间,尽可能针对这些知识有的放矢的多看,多想,多练习,多讨论,多交流。
以便于能更快速的上手工作。
1.1OPNET安装
OPNET安装过程还是比较复杂的,后面有专门的安装说明,这里主要提醒一下,在安装之前一定要记得把VC的环境变量进行设置,具体的设置方式网上能搜到,书上也有介绍。
另外我这里的安装文件有8.1和10.0的,建议使用10.0,因为version高,使用界面更傻瓜一些,而且基本上国内那基本介绍OPNET的书里大多是根据10.0做介绍的。
要先安装8.1获得了license再安装10.0,它能自动找到8.1的license。
1.2OPNET书籍选用
国内OPNET的书就那几本,个人感觉都差不多,讲得不够深入。
我一开始在书店买的一本是人民邮电出版社出版的,讲得不详细,我只在学习各种编辑器熟悉菜单的时候用到了它。
图书馆一共有六本OPNET的书,讲解最详细的一本是
清华大学出版的,陈敏编著的,建议采用,我这里也有这个书的电子档。
其它几本可以有选择性的看看:
李馨,叶明编的《OPNETModeler网络建模与仿真》的OPNET核心函数介绍章节写得比较好,每个函数的实际应用都写出来了,而且函数也做了相应归类,不多掌握起来快;孟晨编的《OPNET通信仿真开发手册》中的OPNET编程基础部分写得很详实,对一些基本的代码做了介绍,并且对状态机的强制性状态和非强制性状态的区别以及它们的合理使用讲解得很清楚。
当然OPNET学习的最好资料还是OPNET自带的英文帮助Tutorial,上面有各种例子,并且有分类好的最全的核心函数。
1.3OPNET建模机制和仿真流程
学习OPNET之前,熟悉一下OPNET的建模机制和仿真流程是很有好处的,这样更有针对性,不会出现,打完了书上的例子,结果都出来了但是还不清楚自己在干什么的情况。
OPNET采用分层建模的机制,从网络物件层次关系看,提供了三个层次的模型,从低到高依次是进程模型——以状态机来描述协议;节点模型——由相应的协议模型构成,反映设备特性;最上层为网络模型,表现网络的拓扑结构。
三层模型和实际的协议,设备网络完全对应,最大限度的贴近了实际的网络系统。
下面会对OPNET的这三个域——网络域(networkdomain)、节点域(nodedomain)和进程域(processdomain)进行进一步的介绍。
OPNET这三个域分别都对应着相应的编辑器。
网络域有项目编辑器和链路编辑器用来对整个网络的框架进行设计—项目编辑器设计网络大小,节点摆放;链路编辑器设计网络拓扑结构,链路的各种参数进行设计。
节点域有节点编辑器,用于对各个节点内部进行具体的设计,涉及到各个模块的摆放,各个模块属性的设置;进程域有进程编辑器用来对每个模块里所调用的进程进行编程设计,它是最底层的也是设计中的难点所在,进程的编写实现了每个模块的基本功能。
另外还有包格式编辑器用来对系统中所用到的数据包进行设计
,探针编辑器用来收集感兴趣的统计量,ICI编辑器则用来创建,查看,编辑接口控制信息。
一般opnet系统级仿真的基本流程如下:
定义包格式——>定义链路模型——>定义节点模型——>构建网络模型——>收集统计量——>运行仿真,进行程序调试——>观察仿真结果——>进行结果分析
当然在这个流程开始之前就要对整个系统有一个全面的构想,这个顺序只是方便软件的使用,避免重复性的工作。
1.4OPNET中的一些基本概念
1.4.1.对象(Object)
Object是Model的一部分,其可以在model中扮演下面的功能:
a)定义行为
b)创建信息
c)储存和管理信息
d)处理、修改、转发信息
e)对事件作出响应
f)包含其他的object
1.4.2.属性(Attribute)
object的Attribute和一些允许访问Attribute或者使Attribute生效的程序组成了object的接口。
这些程序可以是OPNET自动生成的,也可以是用户编写的。
包含有子object的object称之为复合对象(compoundobject)。
1.4.3.模型属性(ModelAttribute)和属性提升(AttributePromotion)
Attribute除了可以描述object外,还可以用在model上用来表示model的参数。
model的attributes机制可以提高model的可重用性。
具体地说,model的attribute被定义为model的一部分,但同时,他们也出现在object里,他们是在object的model被规定后被object获得的。
这是object的本能操作。
类似这种modelattribute机制,objectattribute也可以被向上传给model,这种机制就是所谓的attributepromotion。
Promotion导致objectattribute不再有值,而是作为model的attribute出现在上层属性中。
对于一路promote到所有model之上的attribute,我们可以把它看作是simulation的attribute。
从而把研究的系统看成是这些attributes的函数。
1.4.4.衍生模型(DerivedModels)
有的时候,我们想只改变一个model的一些attributes就可以得到一个新的model。
这种机制称为模型的衍生(modelderivation)。
衍生出的model称为derivedmodel,被衍生的model称为parentmodel,没有parentmodel的model称为basemodel。
2.OPNET各域入门介绍
2.1.网络域
网络域networkdomain定义了通信网的拓扑结构。
通信的实体是节点nodes。
OPNET提供单向和全双工的点到点链路,也提供总线链路用以允许对任意大小的节点组进行广播通信。
2.2.节点域
节点域nodedomain用来对通信设备进行建模,诸如路由器、网桥、工作站、终端等等。
节点模块Nodemodel是通过节点编辑器NodeEditor生成,通过一些更小的模块(module)来表现。
一些模块具有一定的功能,这些功能已经定义好了,只用通过配置一组内部参数(built-inparameters)就可以了。
它们包括各种各样用来在networkdomain连接通信连路的发送器和接收器。
还有一些模块:
处理器(processors)和队列(queues),也是高度可编程的,它们的动作通过进程(Processmodel)来描述。
2.3.进程域
进程域是最底层的域也是最难上手的域,如果全部使用OPNET自带的进程模块,那么我们永远只能是个OPNET使用者,但如果你想要搭建系统实现自己的一些想法,那么我们必须得学会进程的编写,开发自己的进程模块,上述到软件开发的层次。
进程模型nodemodel中的各个module通过三种链接互连,分别是:
packetstreams,statisticwires,logicalassociations。
Packetstreams传送格式化的消息,我们称为packet。
统计线Statisticwire传送简单的数字信号和控制信息,一般用于一个module用来监测其他module的性能和状态。
Statisticwire和Packetstream都有参数用来配置它们的行为。
Logicalassociations用来确认module之间的绑定。
目前,它们只被用在发送器和接收器之间,用来表明它们在接入到Networkdomain上的链路时,应当被当作一对module来使用。
一个进程(process)可以被认为近似于一个执行程序。
OPNET中的Process是基于Processmodel,他们是在ProcessEditor中定义的。
进程组(processgroup)由许多process组成,这些process都是在同一个processor或者queue中执行。
当仿真开始的时候,每个module只能有一个process,称之为rootprocess。
这个process之后能够创建新的process,他们之后也能再创建其他的process。
在仿真中被创建的process称之为动态进程(dynamicprocess)。
任何时刻只能有一个process处于执行状态。
当一个Process开始执行后,我们说这个process被调用(invoked)了。
当一个process调用另一个process时,调用(invoking)process被暂时挂起直到被调用(invoked)process被阻止(block)。
一个process如果完成了它当前调用的处理就将被阻止。
当invokedprocess被阻止时,invokingprocess就将从它挂起的地方继续执行。
OPNET中的Process能够对中断(interrupt)或者调用(invocation)产生响应。
Interrupt可能产生自processgroup之外的源,或者processgroup中的其他成员,或者这个process自己。
Interrupt一般对应于一些事件,包括消息到达、计时器到时、资源释放或者其他模块的状态改变等等。
OPNET的processeditor使用Proto-C的语言来描述processmodel。
Proto-C基于状态转移图(StateTransitionDiagramsSTD)、一个高级指令库(kernelProcedures)和C或C++的通用部件。
STD定义了模型的各个process所处的状态,以及使进程在状态之间转移的条件。
这种条件称之为transition。
KernelProcedures主要一系列的函数包组成,这些包详见参考文档。
STD在ProcessEditor中生成。
STD除了一些传统的STD具有的能力外,还有一系列扩展:
a)状态变量(StateVariables)。
process可以拥有一些私有statevariables,这些statevariables可以是任意的数据类型,包括OPNET专有的、通用的C/C++、用户定义类型等等。
这种能力使得process能够灵活的控制counter、routingtables、与性能相关的statistics、需要转发的message。
任意组合的statevariable可以在一个process所有的动作和决定中使用。
b)状态执行(StateExecutives)。
通过C/C++语言描述了process进入和离开状态时的操作,典型的操作包括:
修改状态信息,创建或接收消息,更新发送消息的内容,更新统计数据,设置计时器以及对计时器作出响应。
c)转移条件(TransitionConditions)。
通过C/C++语言描述布尔变量,要涉及interrupt的属性以及statevariables的组合。
d)转移执行(TransitionExecutives)。
转移时可能会定义一些通用的操作。
3.OPNET进程编程心得
3.1.OPNET自带模块介绍
OPNET一共有以下几种模块:
进程模块(processor),队列模块(queue),各种类型的发射机和接收机。
其中支持processmodel的能够自觉编写进程进行建模的模块只有进程模块和队列模块,发射机和接收机等出于方便和功能的原因,已经被预定义了,只需编辑其属性即可。
Queue还可以让用户定义内部的子队列(subqueues),以及如何管理这些subqueue的方法。
但是它们的基本建模技术还是相同的。
3.2.OPNET进程驱动原理
所有进程process由interrupt驱动。
所以process的第一个操作就是判断interrupt的类型,进而解析interrupt的属性。
各种中断详见书本。
进程在阻止(Blocked)和活动(Active)两个状态间循环,如果interrupt来了则由blocked进入active,完成操作后回到blocked。
3.3.OPNET中各种变量的区分
OPNET中有三种变量全局变量,状态变量和临时变量。
全局变量生存期最长,作用范围最大,它在仿真的任何时刻,在仿真系统的任何进程都是可见的,因而它经常被用来定义各个进程想要共享公用的一些变量。
比如在仿真EPON时,我将OLT的时钟定义成全局变量,方便各个进程对其的调用。
全局变量是在进程的HB中定义的,它在某一个进程里被主声明,在其它需要调用它的进程中用
“extern”进行外部声明。
状态变量是专属于该进程的,只要该进程被调用它就存在,但是别的进程不能直接访问它,当然通过调用一些函数它还是能够被获知的,它在SV中被定义。
节点的一些统计变量一般采用状态变量,比如EPON仿真中各个ONU内处理模块发送的数据量和数据包的个数等都是用的状态变量。
临时变量生成期最短,它不需要在进程的两次调用之间保持不变,比如for循环中自加变量i,因为只是使用上的需要,并不对它运行的结果关注所以用了临时变量
3.4.各进程间数据共享机制
有三种机制用来作为multipleprocessess下,各个process之间的通信方式:
a)modulememory同模块共享内存:
通过函数op_pro_modmem_install()和op_pro_modmem_access()访问。
为了保证process间通信机制,各个process应当遵循sharedmemory的数据类型,这就要求process都要知道,因而sharedmemory的数据结构定义应当房子外部定义".h"文件中,并包含在每个process的headerblock中。
sharedmemory一开始是没有的,是由process来决定什么时候分配以及分配多大,这些通过op_pro_modmem_access()来完成。
内存的分配一般是通过op_prg_meme_alloc()来完成。
b)父子共享内存:
只有以父子关系联系在一起的process才能访问的私有共享内存。
这种共享内存只能在childprocess由op_pro_create()产生时由op_prg_mem_alloc()分配,且不能被替换。
通过op_pro_parmem_access()访问。
通过op_pro_invoke()通知对方对共享内存的内容进行的修改和,以及对内容的检查。
c)参数内存(argumentmemory)
将内存地址作为op_pro_invoke()的参数传给别的进程用以通信,通过op_pro_argmem_access()来完成访问。
与前两个不同的是,这部分内存不是永恒的。
3.5.进程中输入输出流
当packet从inputstream到达时,接收模块的一个process由于streaminterrupt而被调用。
这个process通过op_intrpt_strm()来获悉这个packet是从哪个stream里来的。
Inputstream通常用非负的整数作为标号(index)。
process通过op_pk_get()和streamindex来获得packets。
通过op_strm_pksize()获悉仍然留在inputstream中的packet的数量。
对于outputstream来说,跟inputstream类似,也有一些函数:
op_pk_send(),op_pk_send_delayed(),op_pk_send_forced(),op_pk_send_quiet()。
也是用非负整数用来作标号。
3.6.进程中状态图
3.6.1.强制和非强制状态(ForcedandUnforcedStates)
process在任意时刻只能处在一个状态下。
process可以根据它收到的interrupt在状态之间转移。
每个状态的执行过程分为两个部分。
进入执行(enterexecutives)和离开执行(exitexecutives),分别在进入和离开该状态的时候执行。
Process定义了两种状态,称之为强制状态(forcedstates)和非强制状态(unforcedstates),分别用绿色和红色表示。
Unforcedstates允许在process在enter和exit之间暂停。
一旦process执行完unforcedstates下的enterexecutives,就被block,并将控制权交还给调用它的其他process。
如果这个process是被SimulationKernel调用的,block就意味着这个event的结束。
但是此时这个process依然被挂起,直到下一个新的调用产生使得它进入当前状态的exitexecutives。
Forcedstates是不允许process等待的。
所以一般它的exitexecutives是空白的。
这是它与Unforcedstates的最大区别。
3.6.2.初始状态(InitialStates)
initialstates是process被第一次调用时的起始位置。
通过setinitialstate或makeinitialstate来设置。
beginsimulationinterrupts是一种moduleattribute,用来完成对initialstate的进入。
通过module的begsimintrpt属性来选择。
当然也可以不选择使用beginsimulationinterrupts而使用普通的interrupt(不推荐)。
3.6.3.状态转移
对于状态转移的规定有四个组成部分:
源状态、目的状态、条件表达式、执行表达式。
可以这样解读:
当处在源状态下,如果条件是真,则执行操作,并且转移到目的状态。
转移条件是布尔表达式。
表达式可能是很多东西复杂东西的组合。
所有支持条件表达式的计算都必须在exitexecutives的末尾执行,因为它们马上就要在后面的计算条件表达式的值时用到。
常用的是使用宏来定义复杂或循环表达式,几乎所有Proto-C的宏都是在headerblock中定义的,宏也可以在外部文件".h"中定义。
然后通过在headerblock中用#include包含进来。
宏的定义是#define。
(跟C几乎一模一样)
3.7.OPNET中ODB调试经验
调试程序应该是新手最花时间的一部分,刚开始那些五花八门的错误甚至可能让人丧失信心,所幸OPNET自带的调试工具已经很强大了。
从错误日志里头可以很清楚的看到一些语法错误。
最难发现的是逻辑错误,对于逻辑错误则需要ODB调试,因为它编译不回报错,只有一步一步跟踪才能发现错误。
ODB指令有很多,这里主要推荐最常用的几条。
首先当然是pktrace和pkstop这两条指令是对数据包进行跟踪,可以观察到数据包是从哪里被创建,途中被哪些进程所读取和设置,最终在哪里被销毁。
这两条命令搭配使用可以很清楚的看到系统的运行情况,但问题在于它需要先知道包的ID号,才能进行跟踪。
如果系统中的包就只有几种,并且每种都可以帮助你分析的话,可以随便猜一个包的ID。
但是有时候你只关注某种数据包的话,这样猜的效率就不行。
比如我仿真EPON时要观察控制帧的情况,而系统内有大量的数据帧,这样随便一猜就猜到了数据帧,可行性就不是很高。
所以这里还需要对进程进行监控,于是推荐以下指令prostop和protrace,这个是对某个进程进行跟踪。
如果要观察某个数据包,可以先监控产生这个包的进程,从ODB窗口就可以读出包的ID号,然后再进行包跟踪就行了。
当然很多时候我们还需要对进程中的一些变量的值,一些语句的执行进行观察来方便我们的纠错。
由于进程很多,如果包跟踪的话很浪费时间,这时候我们可以在该进程里写入:
op_prg_odb_bkpt(“label”);来设置断点,然后在设置断点后写入:
if(op_prg_odb_bkpt(“label”)==OPC_TRUE){printf(……)};在printf里写入你想观察的变量,然后在仿真的时候,通过输入prolstop
另外这组命令还经常与上面的protrace联用,因为运行到该断点后你也许会更想看下该进程接下去是怎么执行的,而不仅仅是这个变量的值。
4.总结
本篇文章重点给大家介绍了OPNET软件入门的一些基本知识,以及学习OPNET过程中需要重点关注的一些问题,希望能让大家少走一些弯路尽快的掌握该软件,方便进行进一步设计。
周强08-06-19
如有侵权请联系告知删除,感谢你们的配合!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OPNET 学习 入门 指南