虚拟设备实现Modbus串行链路与Modbus/TCPIP的互连

来源 :科技与企业 | 被引量 : 0次 | 上传用户:zhlkf99
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  【摘要】Modbus作为第一个用于工业现场的总线协议,应用极其广泛,他包括基于串口的Modbus协议和基于以太网的Modbus/TCPIP协议。文章描述了通过虚拟设备实现了这两种通讯方式的互联并给出了实现细节,提出了虚拟技术具有广泛的应用领域。
  【关键词】虚拟串口;TDI驱动;Modbus
  
  Virtual device make the connection between Modbus serial port and Modbus/TCPIP
  Wang yu ning,fuliang
  (SIASUN ROBOT & AUTOMATION CO,LTD. Liaoning 110168)
  Abstract:Modbus is applied widely as the first bus treaty used in industry.It includes Modbus treaty based on serial port and Modbus/TCP treaty based on ethernet network. The essay realizes the connection of the two kinds of communication and give the realization in details, put forward that the technology of virtual will be used widely
  Key words:virtual serial port;TDI drive;Modbus
  
  引言
   近年來,工业现场总线与工业以太网发展迅速,他们之间的之间的竞争也十分激烈。Modbus/TCP以太网协议由Schneider公司发布,是将Modbus现场总线协议与以太网TCP/IP协议结合而成,使得信息从一个网络传输到另一个网络而不需改变通讯协议成为了可能。IANA委员会给施耐德电气公司分配了已为大家熟知的TCP 502端口,以专为Modbus协议保留,可见,Modbus/TCPIP协议现在已经成为Internet标准。
  虚拟技术就是把物理资源转变为逻辑上可以管理的资源,以打破物理结构之间的壁垒,Modbus/TCPIP以太网协议是以网卡为对外接口,Modbus现场总线协议是以串口与外界通讯,由于硬件的限制,双方是无法通讯的。但通过虚拟技术,使得他们之间的通讯成为了可能,他的好处是不需要通过添加网关这样的硬件。本文通过生成一个虚拟串口设备实现他们之间的互联。
  
  1、虚拟设备实现互连原理
  虚拟设备是如何实现Modbus串行链路与Modbus/TCPIP互联的呢,它采用的是“欺上瞒下”的手段,对上层应用程序,注册成一个标准的串口设备,那么只要用户打开这个虚拟设备,就可以发送所有操作串口的API过来,在收到这些请求之后,因为并非去操作真实串口设备,所以对大部分请求直接返回成功即可。但其中有些请求却是需要去处理的,如创建、读写这些请求,以及串口操作控制码中的超时设置等。通过I/O的写请求包获取到应用程序发往串口的数据,虚拟设备做的工作就是把数据发往真实的网卡。它的实现是通过先打开协议驱动设备(如TCP/IP协议驱动,也称为TDI传输器),通过TDI驱动接口构建I/O请求包(IRP)然后发给协议驱动,协议驱动负责为发送的网络数据添加协议头(如TCP/IP协议的TCP头、IP头),最后把封装好的IP包传给NIC设备驱动进行发送。Modbus协议的网络端在收到数据后进行解析,最终获得Modbus串口端发送的数据。在处理读请求时与写请求类似,获得网络数据后,把数据拷入串口读请求包中后返回。另外,对于Modbus这种主从协议需要处理超时,如在网络上移除从站后,在规定时间内没有从站应答返回,主站应取消对其的读请求,让读请求以失败返回。所以在处理超时请求时,保存这个超时时间,在读请求中启动定时器,在时间到时进行读操作,如果没有数据到来则失败返回。
  
  2、程序实现
  (1)在正式创建虚拟设备之前,需要准备一些工具,就像应用程序使用开发包SDK一样,内核编程使用"Windows Drive Kit",简称WDK。WDK自带所有需要的头文件、库、C/C++语言及汇编语言的编译器与连接器。另外需安装一个虚拟机,因为在本机上直接加载一个内核模块是非常不明智的。如果模块中有错误,很容易导致操作系统蓝屏,这是工作文件可能还没有保存,导致代码丢失。
  (2)首先要解决的是Modbus串行应用程序如何与虚拟串口设备交互的问题,先通过IoCreateDevice函数创建一个设备,每个驱动设备都有一个应用程序可访问的符号链接名(也称为Dos设备名)和其他驱动程序可访问的设备对象名,对于串口设备有一个核态使用的设备名,形如"DeviceSerial(n)"(n对应串口号),对于符号链接名,可通过函数IoCreateSymbolicLink创建一个名为"DosDevicesCOMn"(n对应串口号)的设备,这样应用程序就可以通过CreateFile函数对这个串口设备进行打开了。
  (3)接下来是虚拟串口设备与TCP/IP协议驱动进行交互,是通过协议驱动所创建的设备对象名字"DeviceTcp"和"DeviceUdp",因为本例中是与Modbus/TCPIP交互,所以应绑定"DeviceTcp"设备名。通过这个名字调用内核函数ZwCreateFile对其进行打开操作。对任何设备的打开都可以获得一个文件对象,这个对象表述的是对每个设备的一次"打开",其中会保存一些用于这次打开以及之后使用的相关信息。对"DeviceTcp"设备第一次打开操作时通过对pEa结构的EaName域赋值TdiTransportAddress,返回一个代表传输地址的文件对象,第二次打开操作通过对pEa结构的EaName域赋值TdiConnectionContext,返回一个代表连接端点的文件对象(如果是面向无连接的UDP操作,则不需要这个对象),通过向下层提交 TDI_ASSOCIATIOM_ADDRESS IOCTL码的方式在已打开的连接和已打开的传输地址之间建立联系。接下来就可以进行连接操作(客户端)或者等待接受对方的连接(服务端)。
  (4)当作为Modbus主站(客户端)时,需通过TDI函数向对方发起一个连接,首先需要知道对方的远程IP地址和端口号,因为Modbus端口号已经被固定分配,所以这里端口号可以采用硬编码的方式,为了动态获得远程IP地址,可以在应用程序中将其写入注册表,在此时读出即可。一般来说,在对TDI传输器进行任何操作之前,都需要通过TdiBuildInternalDeviceControlIrp函数创建一个IRP(I/O请求包),把操作类型参数设置成需要操作的类型,如连接操作则设置为TDI_CONNECT值。接下来把从注册表读出的远程IP地址和端口号赋值给TDI_CONNECTION_INFORMATION结构中的TA_IP_ADDRESS中的对应变量,在TdiBuildConnect函数中代入之前需创建好的IRP和TDI_CONNECTION_INFORMATION结构,把IRP设置成连接请求的IRP。最终通过IoCallDriver函数将其下发到底层设备。这个连接IRP绑定了一个事件,如果返回状态为pending值,则调用KeWaitForSingleObject函数在这个绑定的事件上等待,直到连接IRP完成,事件置位,此时判断IoStatus.Status的值,如为零则表示连接成功。
  PIRP pIrp = TdiBuildInternalDeviceControlIrp (TDI_CONNECT, pTcpDevObj, pConnFileObj, &Event, &IoStatus);
  if (NULL==pIrp)
  {status = STATUS_INSUFFICIENT_RESOURCES; break;}
  TA_IP_ADDRESSRmtIPAddr={1,
  {TDI_ADDRESS_LENGTH_IP, TDI_ADDRESS_TYPE_IP,{RmtPort, RmtAddr}}}
  TDI_CONNECTION_INFORMATION
  RmtNode = {0, 0, 0, 0, sizeof(RmtIPAddr), &RmtIPAddr};
  TdiBuildConnect(pIrp, pTcpDevObj,
  pConnFileObj, NULL, NULL, NULL, &RmtNode, 0) ;
  status = IoCallDriver(pTcpDevObj, pIrp);
  if (STATUS_PENDING==status)
  KeWaitForSingleObject(&Event, Executive,
  KernelMode, FALSE, 0);
  对于读请求可以有两种方式处理,一种是当串口读请求到来时先返回pending值,并通过TDI函数创建一个操作类型值为TDI_RECEIVE的IRP进行下发。另一种方式是申请一个环状缓冲区,向TDI传输器注册一个面向端端连接的读回调例程,当有数据到达传输层时,传输层将调用注册的回调函数,参数中携带收到数据缓冲区的指针与长度,在回调函数把数据拷贝到我们已经申请号的环状缓冲区中,当串口读请求到来时只需在定时器时间到时查看环状缓冲区中是否有可讀数据,如有则填充完成IRP返回,如缓冲区为空则返回失败。对于写请求与断开连接操作都与连接请求的处理方式类似。
  (5)当作为Modbus从站(服务端)时,需监听到来的连接并判断是否要与其进行端端连接,为了监听连接需注册一个连接回调函数。当下层驱动调用时,从参数中取得对方的地址信息,其中有两个参数是需要填充返回的,一个是连接上下文信息(CONNECTION_CONTEXT *ppConnCtx),一个是接收IRP指针(PIRP *ppIrp),从回调函数参数中取得对方的地址信息为CONNECTION_CONTEXT结构赋值,然后调用TdiBuildAccept函数,其参数包括一个已创建好的用于处理接受连接请求的IRP,一个已创建并绑定到已打开的传输地址文件对象上的连接端点文件对象,接受连接请求IRP的完成回调函数,一个包含对方地址信息的TDI_CONNECTION_INFORMATION结构。之后设置好连接请求IRP的下层堆栈就可以返回给下层驱动去处理了。如接收IRP返回成功,说明端端连接已建立,就可以在这个连接端点的文件对象上进行收发数据了。连接回调函数实现代码如下:
  NTSTATUSTDIClnEventConnect
  ( PVOID pEventCtx, LONG lnRmtAddr, PVOID
  pRmtClnTA, LONG lnUserData, PVOID
  pUserData, LONG lnOptions, PVOID pOptions,
  CONNECTION_CONTEXT * ppConnCtx,
  PIRP * ppIrp)
  {pTDIClnConn
  pLclConn=(pTDIClnConn)pEventCtx;
  pTDIClientExtensionpDevExt=
  pLclConn->pDevExt;
   PTDI_CONNECTION_INFORMATIONpClientConn = pLclConn->pClientConnInfo;
  PTA_IP_ADDRESSpClientConnInfo=
  (PTA_IP_ADDRESS)、pClientConn->RemoteAddress,
   pTAAddrIp = (PTA_IP_ADDRESS)pRmtClnTA;
  pClientConnInfo->Address[0].Address[0].in_addr=
  pTAAddrIp->Address[0].Address[0].in_addr;
  pClientConnInfo->Address[0].Address[0].sin_port= pTAAddrIp->Address[0].Address[0].sin_port;
  TdiBuildAccept(pDevExt->pIrpAccept, pDevExt->pTcpDevObj, pLclConn->pConnFileObj,
  TDIClnIoCompRtnAcc, pDevExt, pClientConn, NULL );
  IoSetNextIrpStackLocation(pDevExt->pIrpAccept);
  *ppIrp = pDevExt->pIrpAccept;
  *ppConnCtx= (CONNECTION_CONTEXT)pLclConn;
  return STATUS_MORE_PROCESSING_REQUIRED;)
  
  3、结束语
  虚拟设备和真实设备并无本质差别,它一样可以去注册中断去操作真实的设备,他的所谓"虚拟"主要是表现给用户的应用程序看的,如我们实现的虚拟串口给应用程序一个串口的"外表",但内部实际如何实现就不是应用程序关心的问题了,同样的方法可以实现一个虚拟网卡去打开串口在现场总线上收发数据。如今对于虚拟设备的应用已越来越广泛,虚拟磁盘、虚拟光驱、以及能在单机上实现多系统的虚拟机,虚拟设备突破了硬件的局限性,充分的利用了已有的硬件设备资源,实现了更多的功能。
  参考文献
  [1]谭文,邵坚磊.寒江独钓:内核安全编程[M]. 北京:电子工业出版社, 2009,6.
  [2]华镕.从Modbus到透明就绪[M].北京:机械工业出版社,2009,1.
其他文献
柿子香甜可口,維生素丰富,膳食纤维含量也是水果中的翘楚。而螃蟹不仅味美,还富含大量蛋白质。近来,正是这两种食物大量上市的季节。然而,螃蟹和柿子这两种时令食物却有着“同食相克,会长结石”的说法,这是真的吗?  让实验来告诉我们答案。  首先,将螃蟹蒸熟后去壳,剔出蟹肉,在研钵中碾碎,然后将柿子去皮,用纱布过滤后,取20毫升柿子汁,放置在烧杯中。然后用移液管量取2毫升柿子汁与少量蟹肉末混合。当实验员把
结合实践情况,在分析工作面概况的基础上,确立了科学合理的采空区瓦斯抽采工艺,通过应用埋管抽采工艺,瓦斯抽采浓度、抽采纯量均趋于稳定,并经过测量得出上隅角瓦斯体积分数
针对底鼓维护对矿井正常生产及辅助运输造成的影响,提出了用一种新型高分子铺底模块替代传统混凝土硬化路面.对模块主体结构进行设计和力学性能研究,研究结果表明:单面蒙皮格
【摘要】在私法领域对民商事主体的信息权进行研究具有重要的意义,信息权是行使其他权利的基础和前提,民商事主体欲行使其任何权利,均必须以知悉相关信息为必要。在私法领域内保护民商事主体的信息权,体现了追求社会实质正义的价值取向。  【关键词】信息权;私法;价值  就信息权的研究而言,无论是理论成果还是制度构建,在公法领域其远超过在私法领域的程度。从信息权的产生来看,其发源于美国著名记者对于政府信息公开及
73岁的马先生有慢性咳嗽病史20多年,近年來时常因受凉引起疾病的急性发作频繁,而且,即使在充分的缓解期也有轻微咳嗽、咯痰、胸闷、气促,被诊断为:慢性支气管炎(慢支)、阻塞性肺气肿、肺心病。年年发病常住院治疗,一进医院便是用广谱青霉素抗感染;二羟丙茶碱(喘定)解痉平喘;盐酸氨溴索祛痰。并且都是静脉点滴用药。常常须用药1~2周或更长时间才得以使病情好转、稳定。严重时开始还得加用克林霉素点滴2~3日以联
最近1个多月,我发现7岁多的孙子老是说口渴要喝水,比以前吃得更多,但是体重不升反降,我还以为孩子在长身体,没有想太多。前两天,老师打电话过来说孩子在上课时说肚子疼,竟然
由于受煤体破碎和采高等影响,大采高工作面经常发生片帮失稳等破坏。通过对阳煤一矿S8310工作面的片帮机理分析和控制技术应用,改善了煤柱物理力学性能,提高了煤体强度,有效
看中医或阅读相关文章时,我们经常听(看)到医师(作者)说一些如气机不畅,或肝阳上亢等中医专用术语,搞得我们一头雾水。中医常说脏腑,西医也是一样,但是有些不一样的地方。下面为大家介绍肝、脾、肺的中医解读。  肝脏  肝具再生功能,是身体的解毒器  在西医解剖学里,肝脏是在我们身体右边的肚子上方,是以新陈代谢为主要任务的器官。它是人体最大的器官,也是最大的解毒器官以及最大的消化腺。最特别之处是它是身体
长久以来,板蓝根被人们广泛用于防治感冒和流感,当病毒性疫情流行时,板蓝根更是被大派用场。近来,在一些地区公布的可预防H7N9禽流感的药方中,板蓝根不出意外位列其中,连央视也发出感慨:“又有板蓝根”。的确,从非典到手足口病,从甲流到H7N9,每次引人注目的传染病一出现,板蓝根都会作为防治药物走到台前。实际上板蓝根活跃的范围并不止此,在现实生活中它几乎就是个“万能神药”,以至于一些人有病时吃,没病时也
防撞墙是为了防止车辆冲到道路外面或者桥梁外面而设,一般在高速公路桥梁中多见,为了减少车辆对周边区域造成的危险性,防止车辆冲出桥梁,也会设置混凝土的防撞墙。本文作者结合自