.Net开发,RFID中间件

虚拟串口

最近学习了一些WDM驱动的知识,弄了下虚拟串口驱动。虚拟串口就是当计算机上没有相应的串口硬件,通过一个虚拟的串口驱动程序,在计算机上虚拟出若干个串口,这些虚拟出来的串口对于应用层来说就好象是真的有这些串口硬件一样。一般计算机上只有1到2个串口,也可以买几个USB转串口的设备,或者是PCI串口卡,通过这样的途径也只能增加几个串口,这并不能满足一些工业控制行业的需求,可能一台监控计算机上需要同时管理几十台串口设备。通过虚拟的串口加上串口服务器硬件,之间通过TCP/IP把串口数据进行透明传输,应该是一种很好的解决方案,这样就可以实现原先的用户管理串口设备软件的顺利平移。本文对我最近学习情况做一个总结。


     先讲下驱动的开发。找资料的过程也是想当辛苦的,这里推荐一本WINDOWS驱动开发的书,《Programming the Microsoft Driver Model》,Micorosoft Press出版,作者是Walter Oney,网上很多地方都有下载。在WINDOWS平台开发驱动有WINDOWS提供的驱动开发包DDK可用,里面有很多驱动的例子,我用的是WINDOWS 2003 SP1 DDK包,这个在网上也有很多地方可以下载。如果是一个开发驱动的新手,先可以看看与WINDOWS驱动开发的书籍,学习一下驱动开发的理论知识,然后进行实践,看些DDK包里面的代码,进行编译调试。一开始如何编译驱动程序,这个小小的问题,困扰了好几天,网上大都是说如何配置VC6开发环境,配来配去都不成功,下载到的一些驱动的源代码上也只有MAKEFILE文件,没有VC的DSP等工程文件,配了2天也没有弄成功,装上了个DDK,发现其实利用DDK里面的Build EnviromentMent里面就有编译驱动的工具,利用这个编译工具进入需要编译的代码目录,输入Build命令后,就自动编译代码了。还有些细节问题讲一下,如果编译的代码目录上有空格在的话,编译就通不过,去掉空格就可以了,比如你的代码目录是d:/my driver/source,要改成d:/mydriver/source编译才能通过。用到csq.h的驱动,需要2003 DDK支持,老的2000 DDK,XP DDK都不支持,DDK有好多个版本。用DDK编译的驱动分check和free两个版本,check版是调试版本,free是发行版本。还有一个很有用的开发帮助小程序,DebugView,在http://www.sysinternals.com/上可以下载到最新版本,通过DebugView可以看到驱动里面DbgPrint函数输出的信息。NT以上平台都采用WDM驱动模型,WDM驱动结构:处于堆栈最底层的设备对象称为物理设备对象PDO(physical device object),在设备对象堆栈的中间某处有一个对象称为功能设备对象FDO(functional device object),在FDO的上面和下面还会有一些过滤器设备对象(filter device object)。功能驱动程序管理FDO所代表的设备,总线驱动程序管理计算机与PDO所代表设备的连接,过滤器驱动程序用于监视和修改IRP流。驱动程序的装载过程:操作系统的PnP管理器按照设备驱动程序的要求构造设备对象堆栈,总线驱动程序为每一个设备创建一个PDO。创建完PDO后,PnP管理器按照注册表中的信息查找与这个PDO相关的过滤器和功能驱动程序。系统安装程序负责添加这些注册表项,而驱动程序包中控制硬件安装的INF文件负责添加其它表项。这些表项定义了过滤器和功能驱动在堆栈中的次序。PnP管理器先装入最底层的过滤器驱动程序并调用其AddDevice函数。这个函数创建一个过滤器驱动程序。然后AddDevice把PDO连接到过滤器驱动程序上。PnP管理器继续装入并调用每个低层过滤器、功能驱动程序、每个高层过滤器,直到完成整个堆栈。用DDK写驱动只能用DDK里面的函数库,这些函数很多,感觉也很复杂。

虚拟串口开发过程,最好先找到一个标准WDM驱动模型的例子代码,然后在这个代码的基础上做写修改,不然从DriverEntry开始一个一个地写,难度相当大。有了一个WDM驱动的骨架后,再修改就容易些了。驱动开发的大部分结构是是比较固定的,驱动入口函数DriverEntry,下面是一个近乎完整的DriverEntry.
extern "C"
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
  DriverObject->DriverUnload = DriverUnload;     
  DriverObject->DriverExtension->AddDevice = AddDevice;
  DriverObject->DriverStartIo = StartIo;
  DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;   
  DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
  DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;

  return STATUS_SUCCESS;       
}
DriverUnload 指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。 DriverExtension->AddDevice 指向驱动程序的AddDevice函数。PnP管理器将为每个硬件实例调用一次AddDevice例程。
DriverStartIo 如果驱动程序使用标准的IRP排队方式,应该设置该成员,使其指向驱动程序的StartIo例程。 MajorFunction 是一个指针数组,I/O管理器把每个数组元素都初始化成指向一个哑派遣函数,这个哑派遣函数仅返回失败。驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相对应的指针元素,使它们指向相应的派遣函数。

在AddDevice里面用IoCreateDevice来创建设备对象,创建一个串口IoCreateDevice (DriverObject,sizeof(DEVICE_EXTENSION),&deviceObjName, FILE_DEVICE_SERIAL_PORT,FILE_DEVICE_SECURE_OPEN,FALSE,&deviceObject),FILE_DEVICE_SERIAL_PORT代表创建的是一个串口设备。

写好驱动的入口函数以后,后面的工作就是完善入口里面的这些函数,写好这些函数后,驱动就差不多写完了。

实现虚拟串口驱动到TCP/IP通信。有两种解决方案,一种是虚拟一个串口驱动的同时,虚拟出一个与之对应的设备,做桥接用,通过这个桥接设备与虚拟串口做数据交互,再开一个应用程序把桥接设备的数据发送到以太网。另外一种是直接在虚拟串口驱动里面发送接收IP包。做桥接驱动,通过IRP的相互交换实现。直接在虚拟串口驱动中发送接收IP包,由于是在系统内核,WINSOCKET当然是用不了啦,只能用网卡的驱动来发送接收数据,可以用TDI接口进行开发,网上有相关使用的例子。

posted on 2008-10-05 22:54  qhong he  阅读(7479)  评论(0编辑  收藏  举报

导航