首页 OmNeT++手册PPT

OmNeT++手册PPT

举报
开通vip

OmNeT++手册PPTOmNeT++手册带有列表的标题和内容版式在此处添加第一个要点在此处添加第二个要点在此处添加第三个要点22020/3/7什么是OMNeT++??OMNeT++是面向对象的模块化离散事件网络仿真框架。不是:不是仿真器是:一个写仿真模型的基础架构和工具,提供组件和模块,像LEGO积木块一样32020/3/7OMNeT++应用领域有通用架构,应用各种领域:有线和无线通信网络的建模协议建模排队网建模多处理器和其他分布式硬件系统的建模硬件架构的验证复杂软件系统各方面性能评价采用离散事件方法的任何系统通过交换消息映射为实体通信...

OmNeT++手册PPT
OmNeT++手册带有列表的标 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 和内容版式在此处添加第一个要点在此处添加第二个要点在此处添加第三个要点22020/3/7什么是OMNeT++??OMNeT++是面向对象的模块化离散事件网络仿真框架。不是:不是仿真器是:一个写仿真模型的基础架构和工具,提供组件和模块,像LEGO积木块一样32020/3/7OMNeT++应用领域有通用架构,应用各种领域:有线和无线通信网络的建模协议建模排队网建模多处理器和其他分布式硬件系统的建模硬件架构的验证复杂软件系统各方面性能评价采用离散事件方法的任何系统通过交换消息映射为实体通信的任何系统42020/3/7OMNeT++模型OMNeT++模型是由模块组成的,模块之间通过消息传递方式进行通信。OMNeT++的整个模型称为network模型结构通过NED语言描述Messages代表网络中的帧或者包、排队网络中的工作或者客户Gates是模块的输入输出接口Connection(link)用于对物理链路建模,channel具有参数:数据率(datarate)、传播延时(propagationdelay)、误码率(biterrorrate)、误包率(packeterrorrate),connection支持这些参数Module也有参数,在NED文件中指定,或者在配置文件omnetpp.ini中指定52020/3/7OMNeT++模型参数的类型:string、numeric、boolean、XML数据树网络模型拓扑结构使用NED语言描述62020/3/7算法编程模型模块中包含算法;仿真对象由C++类描述OMNeT++模型包含如下几个部分:(1)NED语言拓扑描述,.ned文件;(2)消息定义,.msg文件;(3)简单模块源代码,.h/.cc文件。仿真系统包含的组建:(1)仿真内核:管理仿真和仿真类库(2)用户接口:用于仿真执行,用于调试、显示、批处理仿真执行72020/3/7NED语言NED代表网络描述,是用户描述仿真结构的语言。OMNeT++中,NED可以声明简单模块、连接以及它们组合的复合模块等等。NED语言的特征:继承性、基于组件、接口、层级、包结构、内部类型、元数据注解(属性)NED语言有树形代表的等价形式,可以序列化为XML82020/3/7NED语言表示真实的通信网通信网描述:包含很多节点;每个节点有一个运行的应用程序,应用程序随机发送数据包;节点也是路由;假设应用程序时数据包基础的通信,所以传输层细节可以不用考虑。建模方法:首先,建立一个network;然后,定义一个网络引入信道Channel建立App、Rounting、Queue等模块建立节点复合模块所有对象组合在一起92020/3/7定义一个网络networkNetwork{submodules:node1:Node;node2:Node;node3:Node;...connectionsnode1.port++<-->{datarate=100Mbps;}<-->node2.port++;node2.port++<-->{datarate=100Mbps;}<-->node4.port++;node4.port++<-->{datarate=100Mbps;}<-->node6.port++;...}Network的类型是network,node1、node2...的类型为Node,Node在下面定义。然后定义节点之间的连接,连接点称为gate,port++的意思是将一个gate加入到port[]中,{datarate=100Mbps;}代表数据率为100Mbps102020/3/7定义信道每个连接重复写数据率是很麻烦的,所以,创建一个新的信道类型封装数据率设置networkNetwork{types:channelcextendsned.DatarateChannel{datarate=100Mbps;}submodules:node1:Node;node2:Node;node3:Node;...connections:node1.port++<-->C<-->node2.port++...}112020/3/7简单模块定义定义流量生成器、路由、队列包等类型simpleApp{parameters:intdestAddress;...@display(“i=block/browser”);gates:inputin;outputout;}simpleRouting{...}simpleQueue{...}模块App、Routing、Queue名以大写开头以@开头的单词称为“属性”122020/3/7定义Node复合模块将App、Routing和Queue组成Node模块moduleNode{parameters:intaddress;@display(“i=misc/node_vs,gold”);gates:inoutport[];submodules:app:App;routing:Routing;queue[sizeof(port)]:Queue;connections:routing.localOut-->app.in;routing.localIn<--app.out;fori=0..sizeof(port)-1{routing.out[i]-->queue[i].in;routing.in[i]<--queue[i].out;queue[i].line<-->port[i];}}132020/3/7简单模块的定义使用simple关键字142020/3/7复合模块的定义复合模块将其他模块组成一个单元moduleHost{types:..parameters:..gates:...submodules:..connections:..}152020/3/7组装复合模块的例子moduleWirelessHostBase{gates:inputradioIn;submodules:tcp:TCP;ip:IP;wlan:Ieee80211;connections:tcp.ipOut-->ip.tcpIn;tcp.ipIn<--ip.tcpOut;ip.nicOut++-->wlan.ipIn;ip.nicIn++<--wlan.ipOut;wlan.radioIn<--radioIn;}162020/3/7组装复合模块的例子moduleWirelessHostextendsWirelessHostBase{submodules:webAgent:WebAgent;connections:webAgent.tcpOut-->tcp.appIn++;webAgent.tcpIn<--tcp.appOut++;}172020/3/7组装复合模块的例子moduleDesktopHostextendsWirelessHost{gates:inoutethg;submodules:eth:EthernetNic;connections:ip.nicOut++-->eth.ipIn;ip.nicIn++<--eth.ipOut;eth.phy<-->ethg;}182020/3/7信道channels信道封装与连接有关的参数和行为信道后边有C++类定义默认的类名是NED中的类型名;如果有@class和@namespace属性,默认的类名可以不是NED中的类型名系统内置预定义的信道:ned.IdealChannel,ned.DelayChannel,ned.DatarateChannel。如果引入ned包importned.*,则不需要写前面的ned.。IdealChannel没有任何参数DelayChannel有2个参数:delay、disabledDatarateChannel的参数datarate、ber、per192020/3/7创建一个新的信道channelEthernet100extendsned.DatarateChannel{datarate=100Mbps;delay=100us;ber=1e-10;}通过子类化来添加参数和属性,也可以修改已有的属性channelDatarateChannel2extendsned.DatarateChannel{doubledistance@unit(m);delay=this.distance/200000km*1s;}添加cost属性channelBackboneextendsned.DatarateChannel{@backbone;doublecost=default(1);}202020/3/7参数参数是模块的变量,用于构建拓扑结构,作为C++代码的输入参数的类型有:doubel,int,bool,string,xml。也可以声明为volatile单位可以使用@unit属性来指定参数可以从NED文件或者配置文件omnetpp.ini中读取值212020/3/7参数simpleApp{parameters:stringprotocol;//protocoltouse:"UDP"/"IP"/"ICMP"/...intdestAddress;//destinationaddressvolatiledoublesendInterval@unit(s)=default(exponential(1s));//timebetweengeneratingpacketsvolatileintpacketLength@unit(byte)=default(100B);//lengthofonepacketvolatileinttimeToLive=default(32);//maximumnumberofnetworkhopstosurvivegates:inputin;outputout;}上面的模块有5个参数,其中三个有默认值,222020/3/7参数赋值参数赋值有几个途径:从NED代码赋值、从配置文件omnetpp.ini、从用户交互赋值NED赋值的几个位置:在继承的子类中、NED类型实例化的子模块和连接定义中、包含子模块或者连接的网络和复合模块中。(1)继承的子类中simplePingAppextendsApp{parameters:protocol="ICMP/ECHO"sendInterval=default(1s);packetLength=default(64byte);}232020/3/7参数赋值(2)在复合模块中的子模块中moduleHost{submodules:ping:PingApp{packetLength=128B;//alwayspingwith128-bytepackets}...}(3)在网络的子模块中networkNetwork{submodules:host[100]:Host{ping.timeToLive=default(3);ping.destAddress=default(0);}...}242020/3/7参数赋值(4)在网络或复合模块的参数快中networkNetwork{parameters:host[*].ping.timeToLive=default(3);host[0..49].ping.destAddress=default(50);host[50..].ping.destAddress=default(0);submodules:host[100]:Host;...}*-任何索引下标..是索引下标范围*.、{0..49}.称为模式赋值或者深度赋值**.用于匹配多路元素networkNetwork{parameters:host*.ping.timeToLive=default(3);host{0..49}.ping.destAddress=default(50);host{50..}.ping.destAddress=default(0);submodules:host0:Host;host1:Host;host2:Host;...host99:Host;}networkNetwork{parameters:**.timeToLive=default(3);**.destAddress=default(0);submodules:host0:Host;host1:Host;...}252020/3/7参数赋值(5)在配置文件中赋值Network.host[*].ping.sendInterval=500ms#forthehost[100]exampleNetwork.host*.ping.sendInterval=500ms#forthehost0,host1,...example**.sendInterval=500ms**.ping.sendInterval=500ms**.sendInterval=500ms**.sendInterval=1s+normal(0s,0.001s)#orjust:normal(1s,0.001s)设置值为默认值**.sendInterval=default要求用户输入**.sendInterval=ask262020/3/7表达式NED语言表达式和C语法类似二进制异或#、逻辑异或##、^是指数、+是串联接函数:fabs(),toUpper(),uniform(),erlang_k()表达式可以使用模块参数、门向量、模块向量、当前向量索引等来引用272020/3/7volatilevolatile修饰符使得参数表达式在每次读参数的时候重新计算;非volatile参数只计算一次282020/3/7单位同过添加@unit属性可以为参数设置相关的度量单位simpleApp{parameters:volatiledoublesendInterval@unit(s)=default(exponential(350ms));volatileintpacketLength@unit(byte)=default(4KiB);...}292020/3/7XML参数模块需要复杂数据输入OMNeT++包含XML内置支持。读取DTD验证文件,缓存文件,使用XPath子集选择文档部分,提供DOM形式对象树的内容。使用类型xml,通过xmldoc()函数将xml类型参数指向一个xml文件simpleTrafGen{parameters:xmlprofile;gates:outputout;}moduleNode{submodules:trafGen1:TrafGen{profile=xmldoc("data.xml");}...}<?xml><root><profileid="gen1"><param>3</param><param>5</param></profile><profileid="gen2"><param>9</param></profile></root>moduleNode{submodules:trafGen1:TrafGen{profile=xmldoc("all.xml","/root/profile[@id=’gen1’]");}trafGen2:TrafGen{profile=xmldoc("all.xml","/root/profile[@id=’gen2’]");}}302020/3/7XML参数simpleTrafGen{parameters:xmlprofile=xml("<root/>");//emptydocumentasdefault...}使用xml()函数创建一个xml类型的变量312020/3/7门门是模块的连接点有三种类型:input、output、inout一般NED要求所有门都有连接,为了放松这个条件,可以使用@loose来注解simpleGridNode{gates:inoutneighbour[4]@loose;}如果输入门收到的消息是sendDirect()函数发出的,使用注解@directInsimpleWirelessNode{gates:inputradioIn@directIn;}322020/3/7子模块复合模块包含的模块,称为子模块。子模块有名、类型。可以静态指定,也可以通过字符串表达式来指定(这种特性称为参数化子模块类型);NED支持子模块数组和条件子模块,子模块数组的大小必须明确指定)添加子模块,可以对已有的复合模块子类化moduleNode{gates:inoutport[];submodules:routing:Routing{parameters://thiskeywordisoptionalroutingTable="routingtable.txt";//assignparametergates:in[sizeof(port)];//setgatevectorsizeout[sizeof(port)];}queue[sizeof(port)]:Queue{@display("t=queueid$id");//modifydisplaystringid=1000+index;//usesubmoduleindextogeneratedifferentIDs}connections:...}332020/3/7子模块子模块或者子模块向量可以是条件的。if关键字和条件放在子模块类型的后面moduleHost{parameters:boolwithTCP=default(true);submodules:tcp:TCPifwithTCP;...}342020/3/7连接连接在复合模块的connections节中定义连接不能跨层级;2个子模块门可以连接,子模块门和父模块的内部门可以连接input、output门使用箭头连接;inout使用双箭头连接<-->;2个门连接有信道,则使用2个箭头,并将信道放在箭头之间。@display属性也一样。inout门是input和output两个门胶合在一起的,如果需要的时候,可以分开,分别为port$i和port$o门的引用形式是:modulespec.gatespecgatename++表示使用第一个没有连接的门连接352020/3/7信道规约用户自定义信道a.g++<-->Ethernet100<-->b.g++;a.g++<-->Backbone{cost=100;length=52km;ber=1e-8;}<-->b.g++;a.g++<-->Backbone{@display("ls=green,2");}<-->b.g++;内置信道a.g++<-->{delay=10ms;}<-->b.g++;a.g++<-->{delay=10ms;ber=1e-8;}<-->b.g++;a.g++<-->{@display("ls=red");}<-->b.g++;362020/3/7信道名称语法类似于子模块定义:name:typer1.pppg++<-->eth1:EthernetChannel<-->r2.pppg++;a.out-->foo:{delay=1ms;}-->b.in;a.out-->bar:-->b.in;如果没有明确信道名称,信道名词来自于@defaultname属性channelEth10Gextendsned.DatarateChannellikeIEth{@defaultname(eth10G);}372020/3/7多连接链moduleChain{parameters:intcount;submodules:node[count]:Node{gates:port[2];}connectionsallowunconnected:fori=0..count-2{node[i].port[1]<-->node[i+1].port[0];}}382020/3/7多连接2叉树simpleBinaryTreeNode{gates:inoutleft;inoutright;inoutparent;}moduleBinaryTree{parameters:intheight;submodules:node[2^height-1]:BinaryTreeNode;connectionsallowunconnected:fori=0..2^(height-1)-2{node[i].left<-->node[2*i+1].parent;node[i].right<-->node[2*i+2].parent;}}392020/3/7多连接随机图moduleRandomGraph{parameters:intcount;doubleconnectedness;//0.0<x<1.0submodules:node[count]:Node{gates:in[count];out[count];}connectionsallowunconnected:fori=0..count-1,forj=0..count-1{node[i].out[j]-->node[j].in[i]ifi!=j&&uniform(0,1)<connectedness;}}402020/3/7连接模式全图的子图每个节点互连枚举所有的连接412020/3/7参数化子模块类型子模块可以用类型string的模块参数来指定,语法是使用like关键字networkNet6{parameters:stringnodeType;submodules:node[6]:<nodeType>likeINode{address=index;}connections:...}INode是一个存在的接口422020/3/7参数化子模块类型<>之间可以使用表达式networkNet6{parameters:stringnodeTypePrefix;intvariant;submodules:node[6]:<nodeTypePrefix+"Node"+string(variant)>likeINode{...}432020/3/7参数化子模块类型尖括号之间的表达式可以为空moduleNode{submodules:nic:<>likeINic;//typenameexpressionleftunspecified}这时候,子模块类型名通过typename模式赋值来定义networkNetwork{parameters:node[*].nic.typename="Ieee80211g";submodules:node:Node[100];}442020/3/7参数化子模块类型尖括号之间也可以指定一个默认值,用于typename没有赋值的时候moduleNode{submodules:nic:<default("Ieee80211b")>likeINic;...}452020/3/7参数化连接类型和参数化模块类型类似a.g++<--><channelType>likeIMyChannel<-->b.g++;a.g++<--><channelType>likeIMyChannel{@display("ls=red");}<-->b.g++;类型表达式可以为空,所以类型使用typename模式赋值a.g$o[0].channel.typename="Ethernet1000";//A->Bchannelb.g$o[0].channel.typename="Ethernet1000";//B->Achannel还可以给定默认值a.g++<--><default("Ethernet100")>likeIMyChannel<-->b.g++;a.g++<--><default(channelType)>likeIMyChannel<-->b.g++;462020/3/7元数据注解(属性)NED属性是元数据注解,能够添加到模块、参数、门、连接、NED文件、包和NED任何元素上。提过的属性:@display,@class,@namespace,@unit,@prompt,@loose,@directIn使用属性,可以让NED元素挂接额外的信息,一些属性由NED解释,一些由仿真内核解释;其他属性用于仿真模型以内。属性作用于类型@namespace(foo);//filepropertymoduleExample{parameters:@node;//moduleproperty@display("i=device/pc");//modulepropertyinta@unit(s)=default(1);//parameterpropertygates:outputout@loose@labels(pk);//gatepropertiessubmodules:src:Source{parameters:@display("p=150,100");//submodulepropertycount@prompt("Entercount:");//addingapropertytoaparametergates:out[]@loose;//addingapropertytoagate}...connections:src.out++-->{@display("ls=green,2");}-->sink1.in;//connectionprop.src.out++-->Channel{@display("ls=green,2");}-->sink2.in;}472020/3/7属性索引属性索引用于具有同样名字的多个属性,属性索引位于属性名之后方括号中的数字或者标识符simpleApp{@statistic[eed](title="end-to-enddelayofreceivedpackets";unit=s);@statistic[jitter](title="jitterofreceivedpackets");}上例声明了2个统计属性@statistic,属性索引可以方便地使用C++API访问;例如询问“statistics”的索引,会返回包含“eed”和“jitter”的列表。属性索引也可以通过继承重载simpleDummy{@foo[1](what="apples";amount=2);@foo[2](what="oranges";amount=5);}simpleDummyExtextendsDummy{@foo[2](what="grapefruits");//5grapefruitsinsteadof5oranges}482020/3/7数据模型属性可能也包含数据不包含值@node;@node();//sameas@node包含一个值@class(FtpApp2);包含一个列表@foo(Sneezy,Sleepy,Dopey,Doc,Happy,Bashful,Grumpy);包含键值对@foo(x=10.31;y=30.2;unit=km);@foo(coords=47.549,19.034;labels=vehicle,router,critical);492020/3/7重载和扩展属性值当子类化NED类型,使用模块类型作为子模块或者使用信道类型作为一个连接,就可以添加新属性到模块或者信道、参数和门中,也可以修改现有的属性。-代表移除相应位置的元素502020/3/7包当一个项目增长时,迟早有必要引入一个目录结构,NED支持目录树结构,将这些目录称为包。包可以减少命名冲突当仿真运行时,仿真内核需要确定包树的根目录;然后遍历整个目录树,加载每个目录中的NED文件;可以有多个NED目录树,但是它们的根目录存在放在内核的NEDPATH变量中。指定NEDPATH环境变量的几个途径:在系统环境变量NEDPATH中指定;在配置文件ned-path中指定;作为一个命令行选项加入仿真运行库总(-n)。在NED文件中,包名在最上面声明packagea.b.c;512020/3/7包-package.nedpackage.ned有一个特殊的作用,它们代表整个包。注释当作包的文档;该文件中@namespace属性影响该目录下所有的ned文件和下面的目录。顶层package.ned用于指定根包,使得包名导致的目录层数减少。如:需要包名org.example.myproject,但是又不想建立这几个目录,就可以在package.ned中定义包名packageorg.example.myproject,其他的NED文件中相应定义该包名。522020/3/7包——命名解析使用import使用like默认包532020/3/7简单模块——仿真概念离散事件系统(DES):状态改变以离散实例发生,事件的发生经历时间为0。假设2个连续事件之间没有其他事件发生,即,状态在2个事件之间不会改变。看作DES(离散事件)的系统可以用DES仿真器进行建模仿真。例如:计算机网络可以堪称DES。包传输开始;包传输结束;重传超时等未来事件集合或者未来事件列表:DES系统能够维护的未来事件集合的数据结构。伪代码描述为:initialize--thisincludesbuildingthemodelandinsertinginitialeventstoFESwhile(FESnotemptyandsimulationnotyetcomplete){retrievefirsteventfromFESt:=timestampofthiseventprocessevent(processingmayinsertneweventsinFESordeleteexistingones)}finishsimulation(writestatisticalresults,etc.)542020/3/7简单模块——仿真概念初始化过程建立代表仿真模型的数据结构;然后,进入循环过程。从FES中得到事件,并处理它们。当没有事件时,仿真过程停止执行。552020/3/7OMNeT++中事件和事件执行的顺序使用那个消息代表事件每个事件使用cMessage类或者其子类代表消息从一个模块发送到另一个模块,“消息发生地”称为“消息目的模块”,消息发生的时间称为消息到达时间。“超时失效”事件的实现是让模块发送消息给自己。事件按照到达时间的顺序从FES中取2个消息遵守的规则:如果到达时间相等,早到达早执行;如果优先级一样,更小调度优先级值得先执行;调度的或者早发送的先执行。562020/3/7仿真时间当前的仿真时间可以使用simTime()函数获得仿真时间使用OMNeT++的C++类型simtime_t代表其他的函数str()返回字符串值parse()将串转换为SimTimeraw()返回int64类型的值getScaleExp()返回全球指数(theglobalscaleexponent)getMaxTime返回当前指数代表的最大仿真时间兼容性:早期版本使用double作为仿真时间。加入预处理符号USE_DOUBLE_SIMTIME就可以使用double来代表simtime_t还有一些其他的宏572020/3/7FES的实现FES使用binaryheap来实现的,(二叉堆)虽然skiplist跳表性能比堆更好,但是堆认为是最好的算法。FES在cMessageHeap类中实现582020/3/7组件、简单模块、信道OMNeT++仿真模型包括模块和连接模块可以是简单模块,也可以是复合模块简单模块是模型中的活跃组件,行为可以使用C++代码定义连接时信道对象的联系,信道对象封装信道的行为:传播和传输时间建模、误码建模以及其他行为。信道也是用户用C++代码定义的模块和信道的代表类分别为:cModule和cChannel;简单模块代表类为cSimpleModule;复合模块使用cModule实例化cChannel包括三个内置信道类型:cIdealChannel、cDelayChannel和cDatarateChannel592020/3/7组件、简单模块、信道类继承图如下所示:简单模块和信道通过子类化创建时需要重新定义一些函数:initialize():用于初始化代码,在仿真系统安装网络之后调用。finish():当仿真器成功终止时调用,用于总统计量的记录。定义简单模块的动态行为,需要重定义下面的一个成员函数:handleMessage(cMessage*msg)无论何时模块收到一条消息时,调用该函数activity():在仿真器开始的时候,以一个协同程序开始,仿真结束时终止。消息通过receive()获得,仿真时间在receive()中流逝总的来说,handleMessage比activity要好用一些。602020/3/7定义简单模块类型简单模块类型就是从cSimpleModule子类化得到的C++类,通过重定义一个或者多个虚函数来定义行为。该类必须通过Define_Module()宏在OMNe++中注册,Define_Module()宏放在.cc或者.cpp文件中//file:HelloModule.cc#include<omnetpp.h>classHelloModule:publiccSimpleModule{protected:virtualvoidinitialize();virtualvoidhandleMessage(cMessage*msg);};Define_Module(HelloModule);//registermoduleclasswithOMNeT++voidHelloModule::initialize(){ev<<"HelloWorld!\n";}voidHelloModule::handleMessage(cMessage*msg){deletemsg;//justdiscardeverythingwereceive}612020/3/7定义简单模块类型为了能在NED文件中使用上述建立的模块类型,需要一个相关的NED声明simpleHelloModule{gates:inputin;}构造函数:简单模块是仿真内核直接实例化,而不是用户进行的。这就意味着不能随意写构造函数,签名必须由仿真内核指定。幸运地是,这条协议很简单:构造函数必须是public,且没有参数publc:HelloModule();cSimpleModule本身有2个构造函数:cSimpleModule();cSimpleModule(size_tstacksize)用于接收协同程序的堆栈尺寸。前者用于handleMessage,后者用于activity()HelloModule::HelloModule(){...}HelloModule::HelloModule():cSimpleModule(){...}//使用handleMessageHelloModule::HelloModule():cSimpleModule(16384){...}//选择activity622020/3/7初始化和结束过程构造函数、析构函数、initialize、finish四个函数有下面使用惯例:构造函数:将模块的成员变量指针设为NULL;其他初始化工作放到initialize中initialize:进行初始化任务。读模块参数、初始化类变量、使用new分配动态数据结构、分配和初始化自定义的消息、计时器。finish:记录统计。不要delete任何对象,不要取消计时器析构函数:delete所有使用new创建的对象,使用cancelAndDelete删除自消息(计时器)632020/3/7调用顺序最初的事件(startermessages)放入FES所有模块的initialize函数进入事件循环第一个事件被处理...结束事件循环所有模块的finish函数复合模块的initialize子模块initialize如果仿真器因为运行时错误而终止,finish函数不会被调用finish调用方式和initialize相反。子模块finish复合模块finish642020/3/7调用顺序调用顺序的伪代码描述performsimulationrun:buildnetwork(i.e.thesystemmoduleanditssubmodulesrecursively)insertstartermessagesforallsubmodulesusingactivity()docallInitialize()onsystemmoduleentereventloop//(describedearlier)if(eventloopterminatednormally)//i.e.noerrorsdocallFinish()onsystemmodulecleanupcallInitialize(){calltouser-definedinitialize()functionif(moduleiscompound)for(eachsubmodule)docallInitialize()onsubmodule}callFinish(){if(moduleiscompound)for(eachsubmodule)docallFinish()onsubmodulecalltouser-definedfinish()function}652020/3/7多阶段初始化仿真模型中,如果initialize提供的一个阶段初始化不够用,可以使用多阶段初始化,这个功能是通过重定义voidinitialize(intstage)、intnumInitStages()const两个函数来实现的。仿真开始时,initialize(0)被调用,然后initalize(1)、initialize(2)。。。依次被调用。numInitStages返回需要初始化阶段的数目,例如,2级初始化中,numInitStages返回2,initialize(intstage)必须实现stage=0和stage=1的处理过程。callInitialize函数执行所有模块和子模块的多阶段初始化如果没有定义多阶段初始化函数,默认的行为是单级初始化:numInitStage返回1,默认initialize(intstage)简单调用initialize()662020/3/7“End-of-Simulation”事件OMNeT++没有使用仿真结束事件672020/3/7cSimpleModule添加功能——handleMessage()handleMessage函数被每个事件调用想法就是,每个事件发生(消息到达)的时候调用一个用户定义的函数。handleMessage是cSimpleModule的虚成员函数,函数体默认是空的,在子类中用户需要重新定义,并添加消息处理的代码。模块每个消息到达的时候,handleMessage函数会被调用仿真器中的事件循环同时处理activity和handMessage函数,对应于如下的伪代码:带有handleMessage的模块不是自动开始的:仿真内核只为带有activity的模块创建开始消息startermessage。这就意味着,必须从initialize函数调度自消息self-messages,才可以让handMessage模块自己开始工作,不是从其他模块收到第一个消息。while(FESnotemptyandsimulationnotyetcomplete){retrievefirsteventfromFESt:=timestampofthiseventm:=modulecontainingthiseventif(mworkswithhandleMessage())m->handleMessage(event)else//mworkswithactivity()transferTo(m)}682020/3/7handleMessage编程为了在简单模块中使用handleMessage机制,应该为模块指定堆栈大小为0。在handleMessage中能使用的函数有send、scheduleAt、cancelEventsend()这一类的函数:发送消息给其他模块scheduleAt():调度一个事件(模块“发送消息给自己”)cancelEvent():删除由schedleAt函数调度的事件不能在handleMessage中使用receive和wait函数,因为它们天然是协同程序基础的,用于activity想保存的每个数据信息必须在模块类中添加为数据成员,不能够作为handleMessage的本地变量存储。同时,也不能存放在静态变量中,因为静态变量在类的所有实例中共享。加入模块类中的数据成员变量包括如下的情形:状态、属于模块状态的其他变量(重试次数、包队列等)、计算/获取的一次值保存(模块参数值、门索引、路由信息等)、统计集合的变量/对象。这些变量都可以在initialize函数中初始化。initialize的另一个任务是初始化首次触发handleMessage的最初时间,首次调用之后,handleMessage必须注意为自己调度事件以保持“链”不会断裂。692020/3/7应用领域handleMessage在大多数情况下比activity要好(1)当希望模块用于包括几千个模块的大规模仿真,这种情况下,activity的模块堆栈大小会消耗很多内存。(2)对不维护状态信息的模块,如包sinks,handleMessage更方便。(3)有大规模状态空间和许多任意状态转移可能性的模块,这些模块的算法使用activity会很复杂,更适合handleMessage。这种情况更加适合通信协议。702020/3/7应用领域——例子1协议模型通信网的协议层模型在上层有公共的结构,它们都响应3类事件:来自于上层协议的消息、来自底层协议的消息、计时器和超时消息(即自消息)classFooProtocol:publiccSimpleModule{protected://statevariablesvirtualvoidprocessMsgFromHigherLayer(cMessage*packet);virtualvoidprocessMsgFromLowerLayer(FooPacket*packet);virtualvoidprocessTimer(cMessage*timer);virtualvoidinitialize();virtualvoidhandleMessage(cMessage*msg);};voidFooProtocol::handleMessage(cMessage*msg){if(msg->isSelfMessage())processTimer(msg);elseif(msg->arrivedOn("fromNetw"))processMsgFromLowerLayer(check_and_cast<FooPacket*>(msg));elseprocessMsgFromHigherLayer(msg);}712020/3/7应用领域——例子2简单流量产生器和接收器PacketGenerator::handleMessage(msg){createandsendoutanewpacket;schedulemsgagaintotriggernextcalltohandleMessage;}PacketSink::handleMessage(msg){deletemsg;}PackageGenerator需要重定义initialize,以创建m以及调度第一个事件722020/3/7应用领域——例子2简单流量产生器和接收器classGenerator:publiccSimpleModule{public:Generator():cSimpleModule(){}protected:virtualvoidinitialize();virtualvoidhandleMessage(cMessage*msg);};Define_Module(Generator);voidGenerator::initialize(){//schedulefirstsendingscheduleAt(simTime(),newcMessage);}voidGenerator::handleMessage(cMessage*msg){//generate&sendpacketcMessage*pkt=newcMessage;send(pkt,"out");//schedulenextcallscheduleAt(simTime()+exponential(1.0),msg);}732020/3/7应用领域——例子3脉冲流量产生器更为现实的例子是传输包脉冲的发生器,包含burstLength的包classBurstyGenerator:publiccSimpleModule{protected:intburstLength;intburstCounter;virtualvoidinitialize();virtualvoidhandleMessage(cMessage*msg);};Define_Module(BurstyGenerator);voidBurstyGenerator::initialize(){//initparametersandstatevariablesburstLength=par("burstLength");burstCounter=burstLength;//schedulefirstpacketoffirstburstscheduleAt(simTime(),newcMessage);}voidBurstyGenerator::handleMessage(cMessage*msg){//generate&sendpacketcMessage*pkt=newcMessage;send(pkt,"out");//ifthiswasthelastpacketoftheburstif(--burstCounter==0){//schedulenextburstburstCounter=burstLength;scheduleAt(simTime()+exponential(5.0),msg);}else{//schedulenextsendingwithinburstscheduleAt(simTime()+exponential(1.0),msg);}}742020/3/7使用handleMessage的优势和限制优势:消耗更少的内存、调用速度快限制:本地变量不能存放状态信息;需要重新定义initialize752020/3/7activity()处理过程描述使用activity,可以想编写操作系统进程或线程一样对简单模块进行编程,可以等待输入消息,可以停止执行一段时间,当activity退出时
本文档为【OmNeT++手册PPT】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
机构认证用户
夕夕资料
拥有专业强大的教研实力和完善的师资团队,专注为用户提供合同简历、论文写作、PPT设计、计划书、策划案、各类模板等,同时素材和资料部分来自网络,仅供参考.
格式:ppt
大小:2MB
软件:PowerPoint
页数:0
分类:互联网
上传时间:2021-05-21
浏览量:5