一个驱动程序中是不是可以建立多个设备对象,而这些设备对象是不是共用相同的派遣例程?

chely   2009-7-22 16:00 楼主
问题:一个驱动程序中是不是可以建立多个设备对象,而当针对不同的这些设备对象发送的IRP是不是共用相同的派遣例程?

问题产生的背景:
    我要写一个监视串口的过滤驱动.从思路是这样的,在驱动中建立一个过滤串口设备对象将其挂在串口驱动上,再建立一个控制设备对象(用于给应用程序发送过滤串口设备对象监视得到的数据)不挂接,驱动程序中有DriverObject->MajorFunction[IRP_MJ_READ] = ComSpy_Read等派遣例程;

1.这样一个驱动程序中建立2个设备对象可不可以.

2.我想知道的是当有别的应用程序向串口读写经过我的过滤程序时和我用ReadFile,WriteFile向读写驱动程序中控制设备对象时是不是都触发使用驱动程序中相同的派遣例程,例如:向串读和我用ReadFile读时是不是都会调用ComSpy_Read(注意:一个是针对过滤串口设备对象,而另一个是针对控制设备对象).

初学驱动,原理还不太明白,希望有达人能帮助一下!最好能说说其中的原理及过程让我能加深理解一下驱动开发!

回复评论 (18)

可以在一个驱动中创建多个设备对象,多个设备对象构建成设备对象链表
DRIVER_OBJECT的成员变量DeviceObject指向驱动创建设备对象链表的开始位置
点赞  2009-7-23 17:30
hi,楼上的回答正确但我认为就lz想完成的功能而言,与驱动中是否能够建立多个设备对象无关
如果lz希望写监视串口的驱动,那么必须要包含两个模块,一个模块监听串口事件(由过滤驱动完成),一个模块接受数据(应该为一个应用程序),我不明白为什么需要两个设备对象,因为在我看来你只需要将过滤驱动挂在串口驱动之上,那么所有本来应该发给串口驱动的IRP都会首先打到你的过滤驱动里面,那么你只需要在相应的回调函数里面首先向应用程序发event告知监听数据,然后再将本来要发至串口驱动的IRP包通过 Iocalldriver函数丢给处于驱动对象堆栈下一层的串口驱动就好
点赞  2009-7-24 10:48
建立多个对象后,多个对象是否共用驱动程序中相同的派遣例程?
点赞  2009-7-24 13:01
pDriverObject->MajorFunction[IRP_MJ_CREATE]=XXdispatchroutine;
只是从这行指令就可以看出对象的派遣例程是由程序员在driverentry里面自己指定的,你当然可以让两个对象的派遣例程指向同一个回调函数,前提是最好你的回调函数是可重入的
点赞  2009-7-24 14:26
楼上兄弟,抛开实际应用,是不是可以这样理解,在一个驱动程序中无论建立几个设备对象,也不论其中设备对象是否挂接在什么上或没挂,当相同的IRP请求到来时,都会调用同一个派遣例程.如:我建了一个串口过滤对象,一个磁盘过滤对象,一个独立的设备对象,当IRP_MJ_READ请求到来时,这些对象都会调用,我自己指定的ComSpy_Read回调函数对吗?(前提是ComSpy_Read可重入).

不知道我理解的对不对!
点赞  2009-7-24 15:11
绝对不是!
兄弟,驱动里面的设备对象挂接在哪里,那么相关的IRP才会引发相应的回调函数!
你想想应用程式一般怎么对驱动发irp,那必须是先确定相关驱动的devicename或者符号链接,然后通过create或者open等操作获取device的handle,然后再进行read/write/iocontrol等等操作
ok,反过来,你的驱动怎么收IRP,以标准wdm的驱动为例,必须挂在bus driver(又称PDO,物理设备驱动)上,而你的驱动则是所谓FDO功能设备驱动,你必须在adddevice例程里用Ioattachdevicetodevicestack将你的FDO挂在PDO上,而过滤驱动也类似,也必须将你的过滤驱动以这种形式添加到对应devicestack里,才能接收到对应的IRP
而你上面又是磁盘过滤驱动,又是串口过滤驱动,难道你现在都放在一个驱动的driverentry里(这个实在是山寨啊)?那你的inf准备怎么写?
点赞  2009-7-24 15:40
做不一样事情的驱动为什么要放在一起?如果是相互之间需要通信的话,windows也提供了许多种驱动之间通信的方法,不用这样大杂烩呀
点赞  2009-7-24 15:43
兄弟,再举个例子,如:我在一个驱动程序中建立了两个设备对象,一个是串口过滤设备对象,其挂在系统原有的串口驱动上,又建立一个普通的设备对象,它没挂到任何设备上,只是准备与应用程序通讯时使用.

监视串口时是这样实现的.在驱动程序中有DriverObject->MajorFunction[IRP_MJ_READ] = ComSpy_Read等派遣例程;

     当针对串口过滤设备对象的IRP_MJ_READ来时,其调用ComSpy_Read,在这个函数中将数据写入了一个队列结构中,然后向应用程序发event告知监听数据,应用程序这时是打开的普通的设备对象,收到event后,使用ReadFile来对普通的设备对象发送IRP_MJ_READ,其也调用ComSpy_Read,在这个函数中它从队列结构中读刚才监到的数据.(注:这是个德国佬的程序,已实现并可用).

    我现在迷糊的是,驱动开发中的一些基础知识,也就是上面提到的,是不是一个驱动中建立的多个对象,当相同IRP_MJ_READ请求,都是调用驱动程序所写的ComSpy_Read这样的同一个函数.

(注:从网上得知,驱动程序对象通常有多个与它相关的设备对象,因此它利用DeviceObject指针指向一个设备对象列表,该列表表示驱动程序可以控制的物理设备。是不是这些与它相关的设备对象当IRP_MJ_READ请求时,都调用调用驱动程序所写的ComSpy_Read这样的同一个函数)
   

点赞  2009-7-24 15:58
兄弟,不好意思,我说的是,"抛开实际应用",我就是想知道,驱动程序中关于派遣例程当是上面描述情况时的调用流程.
点赞  2009-7-24 16:01
这个我之前回复过你,如果不谈规范做法也没有什么不可重入的问题,两个设备对象如果注册了同一个回调函数,那windows也得乖乖的给你调啊
点赞  2009-7-24 16:19
如果你想加强驱动开发的基础知识,那么推荐去书店买本张帆的《驱动开发技术详解》,入门很合适的一本书
不过坦白说,你的问题其实与驱动无关,就回调函数而言,如果常驻内存,那么谁注册了windows都得调
点赞  2009-7-24 16:23
兄弟,就是这点不太明白,我在编写驱动程序中,指定了DriverObject->MajorFunction[IRP_MJ_READ] = ComSpy_Read派遣例程; 是不是说,其后建立的多个设备对象就都是注册了同一个回调函数,也会在当IRP_MJ_READ请求时,都调用调用驱动程序所写的ComSpy_Read这样的同一个函数.
点赞  2009-7-24 16:25
是,因为这里注册的是驱动对象回调函数DriverObject->MajorFunction[IRP_MJ_READ] = ComSpy_Read,再多设备对象(deviceobject)都是驱动对象的子集
点赞  2009-7-24 16:32
哈哈!兄弟明白了!就要这点。谢您的帮助!
点赞  2009-7-24 21:35
http://blog.eeworld.net/vangoals/archive/2009/07/20/4363863.aspx
点赞  2009-7-26 12:51
这个可以加精了:)
点赞  2009-7-26 19:36
怎么结贴了还能回复啊,最近正在学这个,下了本张帆的电子版本德在啃,委实艰难啊
点赞  2009-8-31 17:49
引用: 引用 17 楼 dulvtianya 的回复:
怎么结贴了还能回复啊,最近正在学这个,下了本张帆的电子版本德在啃,委实艰难啊

是吗?试试看

点赞  2010-5-24 16:39
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复