OPNET报错总结及注意事项

来源:互联网 发布:linux七日杀服务器 编辑:程序博客网 时间:2024/06/05 16:17

一、报错总结

【报错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总结

1access和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一下才会将原来的删除或覆盖。

2ici的使用

        根据网络协议的分层原则,低层协议通常是不会读取高层数据包中的内容,只是做一下封装。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)能够统计每个节点收到的数据包。在设置好统计量后将其提升到模块属性,方便选择。

8opent自动崩溃的问题

        暑假回来继续使用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);查看是否可以获取。

        保存,关闭。

        运行程序,显示结果如下: