基于反射内存的实时网络系统设计
基于反射内存的实时网络系统设计基于反射内存的实时网络系统设计0 引言在半实物仿真系统中需要实时地传输、操作和分析数据,并在此基础上作出相应的控制,实时网络技术是半实物仿真系统中必不可少技术之一。基于反射内存的实时网络技术目前已发展较为成熟的一种性能优异、概念新颖的实时网络技术1。相对于以往基于TCP/IP或UDP/IP实时网络技术来说,它极大的提高了系统实时通讯、数据反射和信号调试的能力,使分布式仿真系统结构的设计及实现更为简单。本文介绍了基于VMI-5565反射内存卡组建实时网络的方法,并就利用VC+6.0实现实时网络通讯进行了研究。1反射内存通讯原理及实时网络构建1.1 反射内存通讯原理反射内存光纤网络采用了先进特殊的技术,具备了很强的支持分布实时系统的数据传输能力2。在每个需要实时通讯的节点上插入反射内存网卡(节点卡),每块节点卡都有自己独立的局部内存,它通过局部内存映射将网卡上的局部内存映射到主机内存,用户读写网卡上的数据就如同读写主机内存上的数据一样快速方便。另外,每块反射内存网卡又通过网络内存映射,将分布节点卡上的局部内存映射到一个虚拟的全局内存,即每个节点在写入本地节点卡的数据同时也写入所有其他节点卡的内存。这样,用户对本地节点内存的读写相当于对全局内存进行读写,而这个全局内存是所有分布节点都可见反射的,从而实现分布节点间的数据通讯3。通过这种方式,所有的节点能透明并确定地传送中断、消息或者数据块到其他的节点。1.2 VMI-5565实时网络产品简介VMI-5565反射内存产品是美国VMIC公司于本世纪初推出的网络通讯产品系列。其特点是通过驱动软件写到某一个节点反射内存板上某一地址单元的数据,可同时通过HUB自动映射写到实时网络上所有节点的反射内存板上的对应地址单元。同时,也支持直接内存访问(DMA)方式的数据块传输。每块反射内存板通过卡上跳线设置在网络上的唯一ID号。其技术性能指标如下:(1).实时性能:数据传输率可达47.1Mbyte/s到174Mbyte/s;(2). 负载能力:通过选用两种不同型号的反射内存板,具有64M字节至128M字节的可选负载能力;(3). 传输距离:支持10km长度的単模光纤300m长度的多模光纤;(4). 扩展性:単个HUB支持8个节点。通过级联HUB,最多可支持256个节点。1.3 基于反射内存的实时网络构建实时网络现行的网络拓扑结构主要有环型、星型结构等几种结构。一般来说,环形结构组网简单。下面以三个节点为例,简单说明环形结构组网过程。三个节点需要三块VMI5565卡及3根单股光纤。首先将三块卡进行统一编址,分别为节点0、节点1、节点2,并将其插入到对应的计算机中,具体编址方式见2.1节。将节点0的反射内存卡的RX端与将节点1的反射内存卡的TX端连接,同时将节点1的RX端与T节点2的TX端连接,节点2的RX与节点0的TX连接,如图1所示:图1环形拓扑实时网络示意图环形结构组网简单,但是在使用的时候,必须将所有的节点计算机全部打开才能进行通讯,在节点较多时,使用不方便,且容易造成因人为失误而导致仿真试验失败的情况。星型实时网络由一个实时网络HUB和实时节点卡组成。安装了实时网络节点卡的计算机通过光纤连接在HUB上。HUB提供了一个共享内存空间,每个节点在本地都有一个该共享内存空间的映射。当任意一个实时处理机在本地节点卡的内存空间中操作时,HUB内共享内存空间的数据就会被更新。同时,其它节点上的共享内存映射空间中的对应数据会被立即更新。这种实时网络具有低延迟、高传输率的优点,确保所有节点数据快速更新。仍以三个节点为例,说明其结构。其结构图如图2所示:图2 星型拓扑结构实时网示意图星型结构则使用时比较方便,只需打开需用的节点计算机并给HUB加电即可,工作稳定、可靠,但相对环形拓扑结构来说,增加了一个实时网络HUB,相同节点数,需要的光纤也增加了一倍,增加了成本。在具体使用中,可根据节点数量来进行实时网络拓扑结构选择。节点较少时选择环形拓扑,可有效地节省成本,节点较多时,可选择星型拓扑,使用更为方便。笔者参与设计并投入使用的仿真系统采用了星型拓扑结构,该系统共有8个节点,分别对应控制台计算机、视景计算机、程序解算计算机、设备控制计算机等计算机。该系统目前已经成功应与于某半实物仿真系统中。由于该半实物仿真系统不是本文重点内容,在此不做进一步说明。2 反射内存存储空间分配2.1 反射内存编址在组网前,需要对每块反射内存卡进行统一编址,以便反射内存网络形成一致的连续的共享空间而不会发生冲突。在VMI5565反射内存卡上,有一排8个小开关,用这些开关即可完成统一编址。8个小开关全部打开时,内部地址为00000000,对应的反射内存卡为节点0,仅第1个打开时,内部地址为00000001,对应的反射内存卡为节点1,第二个打开为节点2,依次类推,按照二进制编码方式排列,依次为0,1,2,4,8,16,32,单个HUB支持8个节点。2.2反射内存地址空间分配由于实时网络系统的内存地址空间有限,所以每个节点计算机写入内存的数据需科学、合理和严格规划。常用的数据写入方式有两种,第一种是不进行地址空间分配,而按照具体节点进行数据通讯,即将数据发送端直接将所需的数据打包发送到对应的数据接收端。例如,0号节点需要将名为ff的数据传递给1号节点,其语法如下(VC+6.0下):发送方(0号节点):retstatus=RFM2gWrite(rh,1,(void *)ff,sizeof(float)*9);接收方(1号节点):retstatus=RFM2gRead(rh,1,(void *)ff,sizeof(float)*9);此种方式在数据量大的时候,会引起溢出,无法保证同一帧数据的完整性,另外,当一段数据为多个节点同时需要时,此种方法就不够方便。因此,目前常用的方式是将反射内存空间进行分配。反射内存地址空间分配是通过软件接口控制文件定义好所有须使用内存空间的数据变量地址,同类数据连续分配地址单元,以便其它节点的计算机可以用直接内存访问方式一次性快速读取大量数据。同时,由于节点上的计算机在某个时刻写到某一内存地址段的多个数据会在下一仿真周期以新的结果刷新此段数据,为了保证其它计算机节点读到该地址段帧的数据是同一帧的数据,需为这段数据定义专门的地址单元标志该段数据的读写状态。用此种方式时,可利用如下句子进行操作(VC+6.0下):数据写入节点: retstatus=RFM2gWrite(rh,0x500, (void *)ff,sizeof(float)*9);数据读取节点:retstatus=RFM2gRead(rh,0x500,(void *)ff,sizeof(float)*9);数据写入节点只需将ff数据写入到固定的地址(0X500),需要用到此段数据的节点均可到该地址进行读写,此种方式下,发送法不需关注接受方,而只需按照事先约好的数据存储地址写入即可,同样,接受方也是如此。2.3 地址空间分配时的注意事项在反射内存空间地址分配时,须注意所分配的空间应大于所需传递的数据长度并有一定的余量,应按照单个数据的字节数和数据段的数据个数来进行仔细计算所需的存储空间。在地址空间分配及实时通讯过程中,应有专用的数据记录空间和节点,做好试验状态和实验结果的记录。同时在每次仿真开始前应清空射内存中原有的数据,以防造成误操作,从而对仿真设备造成损坏。3 在VC+下的实时通讯协议设计 在VC+下利用反射内存网实现实时通讯之前,要进行驱动安装与环境变量设置。具体内容见参考文献4。设置完成后,方可进行相关操作。在笔者完成的实时系统中,采用VC环消息Message方式进行传递进行。首先是完成头文件加载与反射内存卡打开并使之处于使能状态,随后是等待触发。按照反射内存统一编址方式进行通讯协议设计,具体如下。3.1 反射内存卡初始化及使能 在VC+环境下,首先要完成反射内存卡的头文家加载与发射内存卡打开及使能,参考代码如下:#include "rfm2g.h"/反射内存头文件;Main()If(retstatus=RFM2gOpen(rfmFn,&rh)!= RFM2G_SUCCESS) printf("Cannot open RFM2Gn"); exit(0); if(rh = (RFM2GHANDLE) NULL) printf( "%s> rh = %x ", me, rh ); /判断是否打开成功retstatus=RFM2gEnableEvent(rh,RFM2GEVENT_INTR1); /使能反射内存卡,等待时间触发;3.2 发送接受协议 初始化完成后,通讯开始。为了确保数据实时传输的正确性,数据的发送、接收双方需要握手协议。这一点在牵扯到仿真设备初始化的半实物仿真过程中尤为重要。设发送方在0X500地址处写入TX=1,等待接受方应答信号。接受方在0X500处读到TX并确定TX=1,完成准备工作后在0X1000处写入RX=1。当发送方收到RX并确认为RX=1时,正式数据开始发送,实时仿真开始。双方具体操作如下。3.2.1发送操作 发送方首先进行握手信号发送,等待应答成功后,开始发送数据。仿真过程结束后发送TX=2,通知接收方通讯完成,待到对方应答后,关闭反射内存,实时通讯结束。以发送名为ff数据至0X500为例,整个通讯过程参考代码如下: RFM2gClear(&rh);TX=1;retstatus=RFM2gWrite(rh,0x500, (void *)TX,sizeof(float)*9);/发送TXretstatus=RFM2gSendEvent(rh,32,RFM2GEVENT_INTR1,0x0);/发送消息事件;while(1)retstatus=RFM2gRead(rh,0x51, (void *)RX,sizeof(float)*9); if(fabs(RX-1)<0.000001 ) break;printf("wait RX%lfn",fabs(RX-1);printf("RX Readly.n");/握手成功retstatus=RFM2gWrite(rh,0x500,(void *)ff,sizeof(float)*9);/发送ffretstatus=RFM2gSendEvent(rh,32,RFM2GEVENT_INTR1,0x0);/发送消息If(stop=start)/仿真完成TX=2;retstatus=RFM2gWrite(rh,0x500,(void *)TX,sizeof(float)*9);/发送TXretstatus=RFM2gSendEvent(rh,32,RFM2GEVENT_INTR1,0x0);/发送消息事件;while(1) retstatus=RFM2gRead(rh,0x510,(void *)RX,sizeof(float)*9);if(fabs(RX-2)<0.000001 ) break;printf("wait RX%lfn",fabs(RX-1);printf("Retaime TR over.n");ret