2.10 包函数集
Pk(Packet)函数集是有关处理包、主要数据建模以及封装机制的核心函数的集合。Pk函数集中支持的操作类型包括创建/销毁包、设置/获取包的数据内容以及获取包的特殊属性的信息。
1. op_pk_create_fmt (format_name)
此核心函数的作用是创建一个具有预定义包格式的包,其参数说明如表2-26所示。
表2-26 op_pk_create_fmt()函数的参数说明
参数 | 类型 | 描 述 |
format_name | const char* | 包格式名(名格式是在包格式编辑器中创建的,包格式必须放在模型目录中,否则将发生错误。包格式文件采用.pk.m后缀名) |
1)返回值
Packet*——指向新创建的包的指针,如果发生可恢复错误,则返回OPC_NIL。
2)详解
新创建的包由仿真内核分配,并在调用该函数的进程模型所在的处理器或队列处加入循环。由于采用预定义的包格式,因而新创建的包的某些字段可能采用预先指定的默认值。包的初始大小就是所有字段大小的总和,包的bulk数据大小与包格式无关,初始值为零,可通过函数op_pk_bulk_size_set()进行修改。
包一旦被创建,将被分配一个惟一的ID号。包的创建时间和时间戳均设为调用该函数时的仿真时间,而创建模块和戳模块设为运行调用该函数的进程模块。
此外,该核心函数的安全级别为MT-safe。
3)目的
该核心函数提供了一种获取具有预定格式和默认内容的格式化一的机制。由于字段的数据类型不能更改也不能添加新的字段,因而格式化包是面向特定数据集通信的。采用格式化包的好处就在于其字段可通过名称来标识,这将简化设置时的操作。但需注意的是,字段名必须与预定的包格式中的字段名一致,否则当利用名称来确定字段时将造成性能的下降。
新创建的包被赋予特定的内容,并使用op_pk_send…()和op_pk_deliver…()函数将其从创建模块转发出去,同时将新建包的指针存储到一个进程模型状态变量中,以供稍后再次传输包时使用。
4)错误
Program Abort:内存分配失败。
Program Abort:分段错误(由错误的格式名称参数引起)。
Recoverable Error:包格式不可识别。
Recoverable Error:设置了非法包格式字段。不可在创建设置类型结构字段。
Recoverable Error:设置了非法包格式字段。不可在创建设置类型包字段。
5)相关函数
采用op_pk_nfd_set()设置格式化包的字段。
采用op_pk_send…()或op_pk_deliver…()将包发送到其他模块。
采用op_pk_destroy()销毁无用包。
2. op_pk_copy (pkptr)
此核心函数的作用是创建指定包的复本,其参数说明如表2-27所示。
表2-27 op_pk_copy()函数的参数说明
参数 | 类型 | 描 述 |
pkptr | Packet* | 指向原包的指针 |
1)返回值
Packet*——指向复本包的指针。
2)详解
该核心函数创建一个包,并将指定包的头部复制到新创建的包中。复本包将引用原包的字段,当原包或复本包的某个字段发生改变时,所有字段的复制必须在改变之前完成。
所有格式化包和非格式化包都可以用该函数来进行复制,复本包将具有与原包相同的类型。对结构字段(OPC_FIELD_TYPE_STRUCT)的复制采用与字段分配相关的函数,如函数op_pk_fd_set()或op_pk_nfd_set()。对包字段(OPC_FIELD_TYPE_PACKET)的复制将采取包的递归复制。其他字段类型都作为普通数据项进行复制。
复本包被分配一个惟一的ID。包的创建时间设为调用该函数时的仿真时间,创建模块设为运行该函数的进程的模块。若该函数不是由进程或间接进程函数调用的,那么创建模块的对象ID将设为常量OPC_OBJID_INVALID。包的时间戳和模块是由原包复制而来的,因此戳以复本包字段为准,可通过显式调用op_pk_stamp()对其进行更改。
在复制过程中,原包的路由也将被复制,但并不复制ICI,原包和复本包均通过指针指向同一个ICI。
此外,该核心函数的安全级别为MT-safe。
3)目的
该核心函数提供了一种复制包的机制,主要用于:
产生包的多个洪泛传输。
备份输出的包以供将来重传使用。
4)错误
Program Abort:分段错误(由无效包指针、畸形包或畸形结构/包字段引起)。
Program Abort:总线错误(由对包的结构字段分配无效地址引起)。
Program Abort:包指针为空。
Program Abort:包指针指向已销毁包。
Program Abort:包指针指向未许可包。
Program Abort:内存分配失败。
5)相关函数
采用op_pk_id ()确定复本包的包ID。
采用op_pk_destroy()销毁原包或复本包。
采用op_pk_create()或op_create_fmt()创建不基于其他包的新包。
3. op_pk_destroy (pkptr)
此核心函数的作用是销毁包并释放其内存资源,其参数说明如表2-28所示。
表2-28 op_pk_destroy()函数的参数说明
参数 | 类型 | 描 述 |
pkptr | Packet* | 指向需被销毁的包的指针 |
1)返回值
void——无返回值。
2)详解
当不再使用一个包时,就可以通过该函数将其从循环中移除,释放其内存,并同时销毁与之相关的路由。在销毁包时并不同时销毁与之相关的ICI,因为其他包或进程模型可能仍在使用该ICI。可以使用函数op_ici_destroy()来单独销毁ICI。
包被销毁后,就可重新利用其释放的内存来创建新的包。如果操作失败将导致大量无用数据包的积聚,若这些无用数据包占用了足够的虚拟内存,且不再满足新对象的分配需求,那么最终将导致仿真异常中断。格式化包和非格式化包均可采用该函数来进行销毁。
该函数会自动释放所有结构字段和包字段的内存。不过,如果在销毁前已使用op_pk_nfd_get()获取包的结构字段内容,那么就必须使用op_prg_mem_free()释放结构字段内存。
此外,该核心函数的安全级别为MT-safe。
3)目的
该核心函数提供了一种通过销毁无用包,释放其内存,来使内存循环利用的机制。仿真内核可自由分配释放后的内存。一旦函数正确返回,被销毁包的指针就宣告无效。
4)错误
Program Abort:分段错误(由无效包指针、畸形包或畸形结构/包字段引起)。
Program Abort:总线错误(由对包的结构字段分配无效地址引起)。
Program Abort:包指针为空。
Program Abort:包指针指向已销毁包。
Program Abort:包指针指向未许可包。
Program Abort:包指针指向静态包。
5)相关函数
采用op_pk_create()或op_create_fmt()创建不基于其他包的新包。
采用op_pk_fd_strip()或op_pk_nfd_strip()移除包中的某个字段。
采用op_pk_creation_time_get()确定包被销毁前的生存时间。
4. op_pk_get (instrm_index)
该核心函数的作用是获取到达输入包流的包的指针,并将其从流中移除,其参数说明如表2-29所示。
表2-29 op_pk_copy()函数的参数说明
参数 | 类型 | 描 述 |
instrm_index | int | 所属模块输入包流的索引。 |
1)返回值
Packet*——指向从输入流包流的指针。如果流中无包,则返回OPC_NIL。可首先通过函数op_strm_empty()来确定流中是否包含包。
2)详解
该核心函数获取包的方式有两种,一种是获取在包流中发送的包,另一种是获取由远程模块传送的包,两种获取方式没有任何区别。
安静地发送或传递到输入流(采用函数op_send_quiet()或op_deliver_quiet())中的包不会引起相关模块的中断。如果多个安静包属于同一个输入流,则它们将按到达顺序进行排队,使用函数op_pk_get()只获取输入流队列中到达的第一个包,通过连续调用该函数就可从流中获取剩余的包(可调用函数op_strm_pksize()来获取输入流队列中包的数目)。
由于该核心函数需要进程上下文,因而只有进程模型或进程模型直接或间接调用的函数才能调用该函数。所有非格式化或格式化包均可通过该核心函数获取。
当调用该函数时,若输入流索引超过已存在输入流的最大索引,那么仿真内核将试图分配新的输入流,这样就可通过包传递机制的无限多个输入流中获取包。
此外,该核心函数的安全级别为MT-safe。
3)目的
该核心函数提供了从所属模块获取包的机制。由于该核心函数是进程获取并非自己创建或声明的包的惟一方法,因此大量的进程模型都会采用该函数。
4)错误
Program Abort:核心函数需要进程上下文。
Program Abort:内存分配失败。
Recoverable Error:输入流索引溢出。
5)相关函数
采用op_pk_nfd_send()通过输出流
采用op_pk_nfd_deliver()将包传递到未连模块的输入流中。
采用op_pk_send()或op_pk_deliver()以延时、强制、安静到达方式传递包。
采用op_strm_empty()或op_strm_pksize()确定输入流中是否包含包。
5. op_pk_send (pkptr, outstrm_index)
此核心函数的作用是将包发送到输入包流中,基于当前仿真时间安排包到达某个目的模块的时间,并释放调用进程对包的所有权,其参数说明如表2-30所示。
表2-30 op_pk_send()函数的参数说明
参数 | 类型 | 描 述 |
pkptr | Packet* | 指向被发送包的指针 |
outstrm_index | int | 所属模块输出包流的索引值 |
1)返回值
void——无返回值。
2)详解
该核心函数函数确定了包到达目的模块的时间。到达时间是相对于当前仿真时间而设定的,相应事件随之加入到仿真事件列表中。事件发生在仿真时间结束之前,但并不在执行当前仿真时间已经安排的其他事件之前执行。在执行事件之前,将通过一个流中断来调用目的模块。如果目的模块是一个处理器或队列,相关进程可通过函数op_intrpt_type()来确定中断是否由输入流引起,如果是,则可通过函数op_pk_get()获取该包。
一旦包传给该函数,包的所有权即从调用进程转到目的模块,之前进程将不能再继续调用包。
由于该核心函数需要进程上下文,因而只有进程模型或进程模型直接或间接调用的函数才能调用该函数。所有非格式化或格式化包均可采用该函数。
此外,该核心函数的安全级别Forced serialization。
3)目的
该核心函数提供了在节点内的通过包流相连的模块间传递包的机制。该函数是仿真中进行包传递的最基本函数。此类核心函数提供了延时、强制、安静到达目的模块等功能。在不依赖模块间物理连接的情况下可通过函数op_pk_deliver()来传递包。
函数op_pk_sent()允许包传递到其他在处理器或队列中运行的进程或发信机模块中。
4)错误
Program Abort:分段错误(由无效包指针或畸形包引起)。
Program Abort:包指针为空。
Program Abort:包指针指向已销毁包。
Program Abort:包指针指向未知包。
Program Abort:包指针指向静态包。
Program Abort:在对象或流中传递包失败。
Program Abort:核心函数需要进程上下文。
Recoverable Error:输出流索引溢出。
Recoverable Error:输出流索引未被占用。
5)相关函数
采用op_pk_send_delalyed()发送延时到达的包。
采用op_pk_send_forced()发送包并立即在目的点进行处理。
采用op_pk_send_quiet()发送包但不在目的模块处引起中断。
采用op_pk_send_deliver…()将包传递到模块但并不采用包流。
采用op_pk_get()获取包的指针。
6. op_pk_send_delayed (pkptr, outstrm_index, delay)
此核心函数的作用是将包发送到输出包流中,确定附加一段延时后包到达目的模块的时间,并释放调用进程对包的所有权,其参数说明如表2-31所示。
表2-31 op_pk_send()函数的参数说明
参数 | 类型 | 描 述 |
pkptr | Packet* | 指向被发送包的指针 |
outstrm_index | int | 所属模块输出包流的索引值 |
1)返回值
void——无返回值。
2)详解
该核心函数函数确定了包到达目的模块的时间。到达时间为当前仿真时间加上一段特定的延时,同时相应事件加入到仿真事件队列中。一旦预设了事件,该函数立即将控制权返回给调用进程。如果没有其他高优先级的事件,那么预设事件将在指定的延时后如期执行。在延时期内,调用进程可脱离延时包,执行任何其他事件。因此该函数可用来模拟与包传输相关的时延。当执行该事件时,目的模块将会收到流中断,表示可通过函灵符op_pk_get()获取该包。
一旦包传到该函数,调用进程就不再拥有包的所有权。任何由传递包指针的核心函数调用的发送进程将引起包的所有权错误。该核心函数需要进程上下文,可支持格式化包和非格式化包。
此外,该核心函数的安全级别Forced serialization。
3)目的
该核心函数提供了通过包流相连的模块间传递包的机制。该函数是op_pk_send()的衍生函数,对于模拟由调用进程引起的处理延时或传输延时很有用。op_pk_send()的其他衍生函数提供了强制、安静到达目的模块等功能。在不依赖模块间物理连接的情况下可通过函数op_pk_deliver()来传递包。
函数op_pk_send_delayed()允许包传递到其他处理器或队列中运行的进程或发信机模块中。
4)错误
Program Abort:分段错误(由无效包指针或畸形包引起)。
Program Abort:包指针为空。
Program Abort:包指针指向已销毁包。
Program Abort:包指针指向未知包。
Program Abort:包指针指向静态包。
Program Abort:在对象或流中传递包失败。
Program Abort:核心函数需要进程上下文。
Recoverable Error:输出流索引溢出。
Recoverable Error:输出流索引未被占用。
Recoverable Error:延时值溢出。
5)相关函数
采用op_pk_send ()发送无延时的包。
采用op_pk_send_forced()发送包并立即在目的点进行处理。
采用op_pk_send_quiet()发送包但不在目的模块处引起中断。
采用op_pk_send_deliver…()将包传递到模块但并不采用包流。
采用op_pk_get()获取包的指针。
7. op_pk_nfd_set (pkptr, fd_name, value)
此核心函数的作用是为给定包的某一字段赋值,该字段由其名称确定,所赋的值只能是Int、Double或包字段,其参数说明如表2-32所示。
表2-32 op_pk_()函数的参数说明
参数 | 类型 | 描 述 |
pkptr | Packet* | 指向给定包的指针 |
fd_name | const char* | 字段名 |
value | Vartype | 所赋的值 |
1)返回值
Compcode——确认赋值操作是否成功的完成代码。如果发生可恢复错误,则返回OPC_COMPCODE_FAILURE。
2)详解
函数参数value的声明采用Vartype,它可接受int、double或包指针。核心函数会根据包的内部结构来确定传递给确定传递给参数的是何种类型的字段,从而改变它的字段分配方法。如果给定字段之前未被赋值,则新字段的大小仍由包格式决定,并相应增加包总的大小。
对于int、double和包指针类型,需要指定字段的值。在该函数将包封装到字段中后,调用进程就丧失了对被封装包的所有权,只有用函数op_pk_fd_get()(如果为格式化包,采用函数op_pk_nfd_get())对其进行解封装后,才可重新使用被封装包。
包类型字段采用特殊的方法来动态确定其大小。在用包格式编辑器在包格式中定义了这种类型字段后,字段大小值就记入某数据表中。如果字段值设为“inherited”,则字段大小就为被封装包的大小,从而准确模拟了包的总大小。如果某字段大小在表中值小于等于0,将不考虑任何被封装包的大小,从而支持模拟数据压缩。
此外,该核心函数的安全级别MT-safe。