一、报错总结
【报错1】fatal error C1074: 'IDB' is illegal extension for PDB file
【解决方案】出现该错误的原因是因为用兼容方式打开了OPNET Modeler,取消兼容性即可。
【报错2】报错时显示Model Directory的问题
【解决方案】重新设置项目路径后refresh directory,然后删除op_admin目录,重启Modeler即可。
【报错3】项目运行时卡在init状态不动
【解决方案】进程模型新建时属性begsim intrpt默认为disabled,改为enabled即可。
【报错4】op_stat_reg("Assembly Packet Size", OPC_STAT_INDEX_NONE,OPC_STAT_GLOBAL)用错:在进程模型的 local statistics中声明,而在注册时注册为 GLOBAL statistics。
Simulation Kernel: development, sequential
------
<<< Recoverable Error >>>
Unable to register global stat (Assembly Packet Size). Please check
spelling and include a group name if stat is defined with a group name.
T (0), EV (2), MOD (top.OPS_edge_router.transmission_queue), KP (op_stat_reg)
【解决方案】我新建的进程模型在Interfaces->local statistics和Interfaces->global statistics中未声明局部和全局统计变量,导致出现该报错,加上即可。
【报错5】遇到的其他报错基本可以在我的GitHub个人网站下载到的《OPNET常见错误》中找到解决方案。
二、注意事项
以下部分转载自:OPNET总结
(1)access和get
但凡涉及到access的函数都是以指针的形式访问其指向的区域,调用后不会更改指向区域的内容,如op_pk_nfd_access(),op_prg_list_access() ...,涉及到get和remove的函数会将内存中的内容取出,如op_ok_nfd_get(),op_prg_list_remove(),prg_bin_hash_table_item_remove() ...。但也有例外情况,如获取包流ici的函数op_pk_ici_get(),获取后相应的ici还附着在包上,只有调用op_pk_ici_destroy()或者重新install一下才会将原来的删除或覆盖。
(2)ici的使用
根据网络协议的分层原则,低层协议通常是不会读取高层数据包中的内容,只是做一下封装。opnet中上下层交互的信令通常用ici来传递,即用ici来模拟层间原语。
我一般是分三步走:op_ici_create() -> op_ici_attr_set() -> op_pk_ici_set(),这样就会为每个包安装ici,在计算包大小以及goodput过程中,ici的尺寸是不会考虑在内的。
(3)包域的问题
在包的编辑器中,包“域”的数据类型给定的有: integer, floating point, structure, packet, information, integer(64 bit), packet ID, or object ID,用这些类型来模拟每一册协议单元的字段或数据域。我经常使用的是integer,struct和packet。其中的struct类型需要在头部定义一个结构体类型的数据,代表整个"域"(通常作为头部),packet一般采取inherited上层包的形式,作为数据域。注意struct域可以设置大小,但是该大小与你定义的结构体实际内存占用情况无关,只是代表协议设计中该包域的大小,不会影响程序运行,只会影响统计结果的收集。
(4)慎用op_pk_send_forced()函数
该函数对应的是强制无延迟的发包策略。自己多次在仿真中都出现如下问题:
<<< Recoverable Error >>>
Unable to execute intrpt at process (2)
Process is already within an invocation
当时并无头绪如何解决这个问题,很幸运的是,在碰巧将op_pk_send_forced()函数改成op_pk_send()后问题消失了。就如同Product Documention函数中警示的那样,op_pk_send_forced()函数在多进程交互过程中会导致不可预期的结果。
(5)包的分片和重组
在设计过程中,由于底层协议帧大小的限制通常要对上层的数据包分片,这就需要使用分段缓冲区。缓冲区的创建使用函数op_sar_buf_create(),该函数有两个参数:第一个参数中对应了多个常量标识符,我用到的有两个,OPC_SAR_BUF_TYPE_SEGMENT(对应分段缓冲区)和OPC_SAR_BUF_TYPE_REASSEMBLY(对应重组缓冲区),其中分段缓冲区分段后的数据还可以接着继续被分段。第二个参数也对应了多个常量标识,在分段时我用到的也是有两个,OPC_SAR_BUF_OPT_PK_BNDRY(不将分段打包成固定大小)和OPC_SAR_BUF_OPT_SEG_PAD(将数据打包成固定大小),在重组时用到的为默认参数OPC_SAR_BUF_OPT_DEFAULT。
(6)结构体的设置与获取
get(获取)信息的时候都要取地址,如op_ici_attr_get(recv_high_iciptr, "node_id", & nid_info_get); op_pk_nfd_access (pkptr, "head block", & hb_ptr);
set(设置)的时候不用,如op_pk_nfd_set (bd_pkptr, "head block", hb_ptr, op_prg_mem_copy_create, op_prg_mem_free, sizeof (head_block)); op_ici_attr_set (iciptr, "node_id", nid_info);
(7)关于全局和局部统计量
全局统计量(global)能够统计场景中总共收到的数据包个数,本地统计量(local)能够统计每个节点收到的数据包。在设置好统计量后将其提升到模块属性,方便选择。
(8)opent自动崩溃的问题
暑假回来继续使用opent,软件隔一段时间(几分钟)就会崩溃并自动关闭,出现如下问题:
unhandled vex exception
consult C:\Users\Infonet\op_admin\err_log for more details.
In OPNET,access the information for Help>Error Log>Open.
开始百思不得其解,然后尝试清理电脑中的垃圾,发现不知道在什么时候无意装了麦咖啡杀毒(一向只用360的),卸载后正常了。一些杀毒软件也许与opnet不兼容。
(9)三种进程间内存共享方式
a)module memory同模块共享内存:
通过函数op_pro_modmem_install()和op_pro_modmem_access()访问。为了保证process间通信机制,各个 process应当遵循shared memory的数据类型,这就要求process都要知道,因而shared memory的数据结构定义应当放在外部定义".h"文件中,并包含在每个process的header block中。shared memory一开始是没有的,是由process来决定什么时候分配以及分配多大,这些通过op_pro_modmem_access()来完成。内存的分配一般是通过op_prg_meme_alloc()来完成。
b)父子共享内存:
只有以父子关系联系在一起的process才能访问的私有共享内存。这种共享内存只能在child process由op_pro_create()产生时由op_prg_mem_alloc()分配,且不能被替换。通过 op_pro_parmem_access()访问。通过op_pro_invoke()通知对方对共享内存的内容进行的修改和,以及对内容的检查。
c)参数内存(argument memory)
将内存地址作为op_pro_invoke()的参数传给别的进程用以通信,通过op_pro_argmem_access()来完成访问。与前两个不同的是,这部分内存不是永恒的。
(10)关于不同进程使用同一个struct的问题
不同模块间的struct中的元素必须按照相同的顺序定义,否则不但不会报错,而且会导致读取其中元素数值的错误。
解决方法:将多次使用的struct放在头文件中,每个使用该struct的进程包含一下该头文件即可。
(11)最后记录几个错误记录
op_ev_cancel (ack_event); //可能取消不了,因为中断已结束!!需要加测试条件 if( op_ev_pending (ack_event) == OPC_TRUE)判断当前事件是否还存在。
list中的包发送以后就不能再发了,即使是access也不行。
两个list不能直接赋值,要先create,再init,再copy。
为了使进程同步,在父进程的init状态就要invoke一下子进程。
(12)属性的设置和提取
属性分为节点属性和进程属性,将设置的属性提升至网络层进行设置。
在进程模型设置属性,以发送节点(send)为例
<1>设置进程模型设置:
Interface->Model Attribute,假设我们随便设置属性(以后根据具体仿真需要设置)node_size:
设置完成,单击OK,保存关闭进程模型。
<2>在节点模型将<1> 设置的属性提升至网络层。
右击P_0模块,单击Edit Attributes,查看node_size的值是否为promoted,如果不是则设置为promoted:
单击OK,保存,关闭。
<3>在网络层,右击send节点,单击Edit Attributes。设置属性p_0的值(该值是我随便设的),如下:
单击OK,保存。
<4>提取刚才设置的属性
进入send节点的进程模型,单击设置变量node_size为double型:
单击OK,双击st_0节点的上半部分(初始化模块的上半部分):输入
op_ima_obj_attr_get(op_id_self(), "node_size", &node_size);//获取node_size的属性值赋值给第三个参数(在中设置),第二个参数为在(1)中设置的属性名。
op_id_self(),获取自己的id。
输入:printf("node_size,%10.5f\n", node_size);查看是否可以获取。
保存,关闭。
运行程序,显示结果如下:
原文地址:https://blog.csdn.net/gongxifacai_believe/article/details/78565848