基于OpenDDS和反射内存卡的信息分发技术
2020-03-09
(上海航天电子技术研究所,上海 201109)
0 引言
军事信息系统中的信息分发网络作为数字化战场的中枢,将各种信息按照通信协议规定的格式,实时、快速、自动、保密地进行数据交换,从而实现信息资源共享,最大限度地提高武器平台的作战技能[1]。因此,信息分发网络面临数据的分布性、准确性、实时性、正确性、协调性、和安全性等挑战[2]。 OpenDDS是用于分发实时应用系统数据的网络中间件,简化了分布式应用程序的开发、部署和维护,应用程序简单地发布和订阅数据,发布方和订阅方无需知道对方地址即可通信。其以数据为中心的发布订阅模式极大地减少了在网络上发送数据所需的消耗,为大容量传输网络提供了针对关键数据快速且可灵活配置的传输方法[2-3]。此外,OpenDDS规范还定义了大量的服务质量(Quality of Service, QoS)策略,使得OpenDDS可以很好地配置和利用系统资源,协调通信质量和执行效率之间的平衡,增加了通信的可靠性[4-5]。目前,许多军事领域已广泛采用OpenDDS技术[6]。
OpenDDS是建立在公共对象请求代理体系结构(common object request broker architecture, CORBA)上的应用框架,远程调用通信是其信息分发的主要技术,在订阅发布通信中起到重要作用,默认情况下传输介质为网卡[7-8]。为了进一步提高信息分发的效率,降低网络间通讯的时延,屏蔽子网内部频繁通讯对整个网络中其他设备的干扰,本文使用光纤反射内存卡作为底层传输介质替换网卡,提出一种基于反射内存卡和OpenDDS通信模型的信息分发技术[9-10]。依据CORBA通信的原理,ACE中Reactor监控硬件数据到和多路分离方法,以及反射内存卡应用函数实现相应功能,将本通过DIOP完成的通信使用反射内存实现,设计了OpenDDS下基于反射内存卡的信息分发网络。
1 系统结构及原理
1.1 OpenDDS
OpenDDS采用以数据为中心的发布订阅机制,其通信网络由一个或者多个数据域组成。每个域包含一套域参与者(发布者和订阅者),参与者为网络中分布式通信节点,节点间使用OpenDDS通信。完整的OpenDDS网络域包括域参与者和主题,域参与者又可分为数据写入者、发布者、订阅者、数据读取者。OpenDDS中各分布式节点身份可以是发布者、订阅者或两者兼有,节点间关系平等,数据域内使用主题标识数据,每个主题有唯一的名称、数据类型和一套QoS策略。发布者发布主题和数据,订阅者根据自己需要的主题订阅数据。OpenDDS网络发现模型为集中式发现模型,网络通信节点中除了域参与者,还需要一个DCPSInfpRepo (信息仓库)节点提供发现服务,允许发布者和订阅者通过DCPSInfpRepo根据主题发现彼此。OpenDDS模型提供匿名、对上透明、多对多的通信,通信时随时可有新的节点注册入全局数据空间发布/订阅信息,或随时退出该网络而不影响其余各节点,解决了因网络结构动态变化需要重构整个通信系统的问题,增强了通信组网的灵活性[2-3,11]。
OpenDDS节点框架如图1所示,最上层为应用程序,底层为操作系统和通信介质,OpenDDS作为网络中间件构建在ACE环境和CORBA模型上。其中CORBA使用远程调用完成了分布式通信的功能,ACE完成了操作系统的适配、包装,为CORBA通信提供了框架和模式。本文使用反射内存卡替换远程分布式通信中使用的底层硬件,是在CORBA中间件的基础上实现的。
图1 OpenDDS 节点框架图
1.2 OpenDDS网络通信
集中式发现的OpenDDS网络通信分为分布式远程调用通信和本地通信。信息仓库(DCPSInfpRepo)节点提供发现服务,允许发布者和订阅者通过DCPSInfpRepo根据主题发现彼此.DCPSInfpRepo与发布者和订阅者之间采用远程调用通信。发布者和订阅者相互发现后,发布者直接向订阅者发送数据,使用本地通信。如图2所示。
图2 OpenDDS通信模型
远程调用通信节点使用的Discovery模块包含CORBA中间件,采用基于UDP的DIOP协议,CORBA的核心是ORB (对象请求代理),通过ORB实现了客户端和服务对象的完全分开,客户端不需要了解服务对象的实现过程和具体位置,就可以使用服务对象。本文主要研究OpenDDS基于CORBA的远程通信。
1.3 CORBA通信
CORBA为可移植的、面向对象的分布式计算应用程序解决了远程对象之间的互操作问题。CORBA基于客户端/服务器模型,在OpenDDS框架中,DCPSInfpRepo作为CORBA服务器,发布者和订阅者为客户端。CORBA核心是对象请求代理(Object Request Broker, ORB),通过ORB实现了客户端和服务对象的完全分开,客户端不需要了解服务对象的实现过程和具体位置,就可以使用服务对象。CORBA通信原理如图3所示。
图3 CORBA 通信原理图
CORBA的基本工作方式如下:
1)客户端使用静态存根(IDL STUBS)或动态调用接口(DII)提出请求,将请求传递给ORB内核。
2)客户端ORB内核通过网络传送到与服务器应用程序相连的服务器ORB内核。
3)服务器ORB内核将请求分配给对象适配器(Object ADAPTER),产生目标内核。
4)服务器ORB内核将请求分配给目标对象的伺服程序。
5)伺服程序执行客户机请求后,将结果返回。
客户端和服务器端的ORB必须协同起来完成工作。ORB间通信协议为通用对象请求代理间协议(General Inter-ORB Protocol, GIOP),存在于ORB内核中,结合不同的通信硬件,GIOP可以具体化为很多协议,基于UDP数据报的传输协议是DIOP。DIOP协议框架主要由Acceptor,Connector、Connection Handler、Endpoint、Profile、Protocol Factory、Transport类的子类组成。其中Profile是基于CORBA的IOR定义的,封装了所有创建和解析一个特定协议的IOR所需的全部方法和成员,在ORB启动服务时,Protocol Factory负责根据给定的可插拔协议在服务器端创建一个Acceptor,监听客户端发来的请求,同时为每个客户端启动一个Connector。当客户端涉及对象时,ORB必须获得相应IOR的profile列表。该profile被选定后, Connector注册会将一个具体的connector实例与相应的profile类型进行匹配并向ORB发出连接请求。而Acceptor一旦监听到客户的连接请求,就将他送给ORB处理。只要连接关系确立,客户端与服务器端就可以通过可插拔协议进行数据通信[7-9]。DIOP协议的主要部分继承了7个基类,并加入了自己的特性。
1.4 反射内存卡
反射内存卡类似于共享内存,硬件安装在不同的计算机主机上,所有节点共享同一片存储区域,同一时刻允许系统中所有节点同时读写共享内存。由于不需要通信协议,在任意一块反射内存卡被写入数据后,可以在极短的时间内更新数据,网络上所有计算机都可以访问这个新数据[11],传输延迟小,可以实时进行信息传输,更能满足大型通信网络的数据分发要求。
反射内存卡对于任意节点的数据读写没有硬件限制,在实际使用时需要制定具体的协议监控数据收发,数据的收发监控可以使用查询或中断模式:查询模式需要有监控线程监控数据的读写,中断模式需要使用反射内存卡提供的中断函数。
1.5 ACE Reactor
ACE Reactor处于OpenDDS中的底层模块ACE中间件。ACE Reactor类似一种监控程序,提供多路分离和事件分派框架,简化了事件驱动应用的开发。通过在操作系统事件多路分离接口上进行侦听事件发生,ACE Reactor触发对用户预先登记事件处理器(event handler)对象中方法的回调(callback)。该回调方法由应用开发者实现,其中含有应用程序处理此事件的特定代码[9-10]。
OpenDDS中使用ACE Reactor进行UDP数据的接收和处理,当ACE Reactor监控到某个Socket上UDP数据到达这类事件时,触发此Socket对应的DIOP模块中的事件处理器函数。这样的模式即查询模式,由于ACE Reactor作为OpenDDS底层数据通信重要的环节,当传输介质由网卡替换成反射内存卡时,也使用ACE Reactor对反射内存卡上的数据进行监控。
2 基于反射内存卡通信的硬件设计
2.1 反射内存卡网络地址设计
反射内存卡允许系统中所有节点同时读写共享内存,在OpenDDS分布式网络应用中,设计最大有128个通信节点,需要对每个节点的反射内存卡进行地址分配。反射内存卡的地址以反射内存ID标识,反射内存ID由板卡硬件设置。网络中的节点需要实现ID与UDP协议中的IP地址的对应,这里使用算法:
IP=0xc0a800+ID;
DCPSInfpRepo服务器在网络中心,设置反射内存ID为129,其他反射内存节点为1~127。由此DCPSInfpRepo服务器和其他发布者/订阅者对应的IP地址设为192.168.0.129和192.168.0.1~192.168.0.127。
2.2 反射内存卡节点存储设计
反射内存卡存储区设计如图4所示,每块反射内存卡地址分为2个部分,状态区和数据区,状态区记录每个节点是否可读写,数据区记录每个节点收到的帧内容。由于OpenDDS网络通信分为分布式远程调用通信和本地通信,远程调用通信为DIOP帧,本地通信为DCPS帧。因此每个反射内存卡节点内部还需要针对不同的传输帧划分为2个数据,将节点内部划分地址可以实现数据在单个节点上的分离。这里实现了socket端口到反射内存卡数据区的映射。
图4 反射内存卡存储分配图
3 基于反射内存卡通信的软件设计
3.1 配置OpenDDS 的DIOP协议
OpenDDS使用DIOP前要配置DIOP协议,方法如下:
1)DIOP协议代码被包含在TAO_Strategies库中,将TAO_Strategies.lib加入到OpenDDS应用链接库中。
2)通过服务配置器动态加载DIOP协议:在DCPSInfpRepo应用路径下创建svc.conf文件,输入动态加载DIOP协议指令:
dynamic DIOP_Factory Service_Object*
TAO_Strategies:_make_TAO_DIOP_Protocol_Factory () ""
Dynamic Advanced_Resource_Factory Service_Object*
TAO_Strategies:_make_TAO_Advanced_Resource_Factory ()
"-ORBProtocolFactory DIOP_Factory"
3)修改发布者订阅者应用程序的配置文件dds_udp_conf.ini,将其中的DCPSInfoRepo=corbaloc::192.168.0.129:12345/DCPSInfoRepo
改成DCPSInfoRepo=corbaloc:diop:192.168.0.129:12345/DCPSInfoRepo
4)由于服务器和客户端都需要创建TAO_DIOP_Acceptor,在运行应用程序时,服务器端和客户端需要声明DIOP端点,方法是在命令行数输入-ORBListenEndpoints diop://主机号:端口号。
至此,配置DIOP协议配置完毕。
3.2 DIOP客户端注册
发布者和订阅者作为客户端与DCPSInfpRepo服务器端DIOP通信图如图5所示。
图5 发布者/订阅者与DCPSInfpRepo服务器DIOP通信图
DIOP协议中,客户端DIOP_Connector和DIOP_Acceptor创建的DIOP_Connection_Handler和TAO_DIOP_Transport负责与服务器端实现通信,为保证可以正确收到服务器发送的数据,因此需要在TAO_DIOP_Transport中将DIOP_Connection_Handler注册到反应器上,使得反应器可以监控handler句柄上是否有数据到来。具体操作为在TAO_DIOP_Transport::register_handler函数中加入代码:
ACE_Reactor * const r = this->orb_core_->reactor ();
if(r==this->event_handler_i()->reactor ()){
return 0;
}
this->ws_->is_registered (true);
return r->register_handler (this->event_handler_i (),
ACE_Event_Handler::READ_MASK);
3.3 反射内存卡通信设计
在OpenDDS的DIOP上实现反射内存卡的数据传输,需要解决反射内存卡数据监控问题,这里的数据监控使用程序查询模式,通过ACE Reator触发接收回调函数接收数据。图5描述了在DIOP中使用反射内存卡作为通信介质的实现方法。
如图6所示,在服务器端DIOP_Acceptor类中创建反射内存卡监控线程函数,用于监控数据是否已经写入反射内存,监控到反射内存有数据写完成时通过socket向本机发送可读的1字节数据,ACE Reactor监视到事先注册在其中的socket有数据到来,进而能够触发到事先注册在Reactor中注册的事件处理函数接收数据。反射内存卡监控函数作为一个单独的线程创建位置较为重要,既要满足用于监控网卡数据的socket已经建立并完成监听端口绑定的初始化之后,又要满足发送端发送第一帧数据之前,以确保接收端能及时准确地监控到发送端写入反射内存卡的所有数据。这里监控线程函数的创建位置是DIOP_Acceptor.cpp的open_i函数中。
图6 OpenDDS 反射内存卡替换原理图
在触发接收函数后,在接收数据函数内部从反射内存卡对应地址读出发布端写入的数据。由此,基于DIOP的反射内存卡数据传输,客户端向反射内存写数据,服务器端从反射内存读数据的单词流程得以实现。服务器端向客户端传输数据流程与此类似。
3.4 反射内存卡数据同步
由于发送和接收方是2个不同的进程,而操作反射内存卡的同一块地址范围可能会出现接收端还未将前一次数据取走,发送端已将下一帧数据写入的丢帧问题。为解决数据在反射内存卡中数据共享时的同步问题,程序中创建读写标志位,即设置两个标志:
f1:写入标志位,置位时表示发布端已将完整一帧数据写入反射内存卡对应地址。
f2:读取标志位,置位时表示订阅端已将数据从反射内存卡对应地址读走,此时可写。
标志位配合反射内存读写的流程如图7所示。
图7 反射内存卡读写流程图
1)TAO_DIOP_Transport::send依据读标志f2是否置位,决定是否将将要发布的数据写入反射内存卡,写入后清除读标志f2,置位写标志f1。
2)线程函数ThreadProc依据写标志f1是否置位,决定是否向自己进程的发送1个字节通知数据以便触发ACE reactor,并清除写标志f1。
3)TAO_DIOP_Transport:recv首先通过this->connection_handler_->peer ().recv()接收由线程函数发来的一字节通知数据,从反射内存卡取出订阅的数据,并置位读标志f2。
4 实验结果与分析
实验验证使用3台计算机分别作为DCPSInfoRepo,发布者和订阅者,运行DCPSInfoRepo服务器程序如图8,命令行输入:
DCPSInfoRepo -ORBListenEndpoints diop://192.168.0.129:12345
图8 DCPSInfoRepo服务器运行示意图
运行发布者程序,命令行输入:
./subscriber -ORBListenEndpoints diop://192.168.0.1:10000 -DCPSConfigFile dds_udp_conf.ini
运行订阅者程序,命令行输入:
./publisher -ORBListenEndpoints diop://192.168.0.4:10001 -DCPSConfigFile dds_udp_conf.ini
发布者发送数据,订阅者可以顺利接收到数据,如图9和图10所示。
图9 发布者发布数据
图10 订阅者接收数据
实验结果证明,基于反射内存卡和OpenDDS的通信模型能够顺利实现OpenDDS发布订阅的过程,数据可以正确分发。
5 结束语
以数据为中心的OpenDDS增加了信息分发系统通信的灵活性。反射内存卡作为网络的底层硬件允许系统中所有节点同时读取共享的内存数据,其无需通信协议,减少了网络中不必要的数据,提高了数据的传输效率,是一种非常适合实时信息网络的底层硬件。基于OpenDDS的分层架构,采用修改DIOP协议的方法,使远程调用数据通过反射内存卡传输,实现了基于OpenDDS和反射内存卡的信息分发系统。将反射内存卡和发布/订阅模式结合设计的信息分发网络,更好地满足军事领域中信息分发系统实时性、可靠性的要求。