20楼#
发布于:2005-02-23 15:25
[quote]想了想,为什么不在customerTimerDpc用代码直接取消irp,为什么要调用取消例程再等待呢?Copy/Paste再用些互斥手段不可以吗? 因为自己构造了irp,在取消系统发来的irp的时候,要cancel掉自己构造的irp。而如果cancel自己构造的irp的话,调用IoCancelIrp()后,就会进入完成例程,待到完成例程执行完毕后,再继续执行,所以需要等待,而在customtimerdpc是运行在dispatch_level上的,所以无法等待。 [/quote] 实在不行,就留给System Worker Threads替你做,在customtimerdpc中将释放Irp的工作加入为一个WORK_QUEUE_ITEM。 |
|
|
21楼#
发布于:2005-02-23 17:32
简单的方法
这里有两个irp,一个是应用层发给驱动的irp,一个是驱动自己构造发给下层的irp 在应用程序退出的时候(异常退出或正常退出都可以),以失败状态完成应用层发的irp,然后在完成例程里直接free掉自己构造的irp 如何检测应用程序(异常)退出,简单的办法, 把你得设备属性改为独占使用(避免引用计数),在dispatchcleanup中处理任何应用程序的pending irp 因为应用程序(异常)退出的时候会关闭所有打开的句柄,从而引发DispatchCleanup的调用 |
|
22楼#
发布于:2005-02-24 12:56
简单的方法 \"以失败状态完成应用层发的irp,然后在完成例程里直接free掉自己构造的irp\" 这里的完成例程是指应用程序的IRP的完成例程还是驱动构造的IRP地完成例程?如果是驱动的话,不掉用IoCancelIrp()不会进入完成例程的。 |
|
23楼#
发布于:2005-02-24 17:33
[quote]简单的方法 \"以失败状态完成应用层发的irp,然后在完成例程里直接free掉自己构造的irp\" 这里的完成例程是指应用程序的IRP的完成例程还是驱动构造的IRP地完成例程?如果是驱动的话,不掉用IoCancelIrp()不会进入完成例程的。 [/quote] 当然是自己构造的irp的完成例程,为什么不调用IoCancelIrp就不会进入完成例程? VOID IoSetCompletionRoutine( IN PIRP Irp, IN PIO_COMPLETION_ROUTINE CompletionRoutine, IN PVOID Context, IN BOOLEAN InvokeOnSuccess, IN BOOLEAN InvokeOnError, IN BOOLEAN InvokeOnCancel ); InvokeOnSuccess , InvokeOnError, InvokeOnCancel都设为true,不就行了 |
|
24楼#
发布于:2005-02-24 21:18
[quote][quote]简单的方法 \"以失败状态完成应用层发的irp,然后在完成例程里直接free掉自己构造的irp\" 这里的完成例程是指应用程序的IRP的完成例程还是驱动构造的IRP地完成例程?如果是驱动的话,不掉用IoCancelIrp()不会进入完成例程的。 [/quote] 当然是自己构造的irp的完成例程,为什么不调用IoCancelIrp就不会进入完成例程? VOID IoSetCompletionRoutine( IN PIRP Irp, IN PIO_COMPLETION_ROUTINE CompletionRoutine, IN PVOID Context, IN BOOLEAN InvokeOnSuccess, IN BOOLEAN InvokeOnError, IN BOOLEAN InvokeOnCancel ); InvokeOnSuccess , InvokeOnError, InvokeOnCancel都设为true,不就行了 [/quote] 谢谢你的关注:) 现在的问题是我结束应用程序发来的IRP的时候,对自己构造的irp没有影响,此时这个irp没有被完成,取消或者失败,也就是不会进入完成历程。 这几天作试验发现应用异常结束后,应用发来的IRP的取消历程立即被调用,但是几分钟后系统才调用dispatchCleanup,在这里我把自己构造的irp给cancel掉了,然后进入完成历程进行处理。 在这个过程中,下层驱动从来没有取消过上层驱动发下去的irp。 |
|
25楼#
发布于:2005-02-25 10:16
这个话题,讨论了这么多,还没有解决方案吗?
我觉得大家提的方案都比较可行。选择其中一个就可以了。 还有我在提醒一下: 1、你自己创建发向底层的Irp用的是什么函数?用IoAllocateIrp要简单一些。要是用IoBuildDeviceIoControl的话,系统给你做了很多工作,包括完成这个Irp的释放工作都不用自己关心,但是创建出来的Irp要加入到当前FileObject的队列里边(可能是,记不清楚了)。应用层关闭该fileObject的时候,这些驱动自己创建的Irp必须要完成,否则系统就会等待。至于说会不会象你所说的那样等待几分钟以后还会再发送IRP_MJ_CLEANUP,我不太清楚。反正使用这个函数要小心!我个人则一般用IoAllocateIrp。 2、你在上层Irp的cancel routine中,取消本层创建的Irp的时候,完全没有必要等待它的完成。 这个问题(驱动创建新的Irp)在是DDK的很多例子里边都有涉及。尤其是usb部分的例子。 |
|
26楼#
发布于:2005-02-25 11:59
没明白你的问题所在 |
|
27楼#
发布于:2005-02-26 08:52
既然你设置不管IRP正常完成、失败、取消都要调用完成例程,在完成例程中取消你自己创建的IRP应该是最好的地方
|
|
|
28楼#
发布于:2005-02-27 17:18
我曾经也遇到相似的情况,我的做法是:
用一个列表结构,存储自己构造的IRP指针,当IRP正常完成时,删除掉它,如果异常退出,从列表中找到所有的IRP,Cancel它。不知这种方法对你是否可行。 |
|
|
29楼#
发布于:2005-02-28 09:15
既然你设置不管IRP正常完成、失败、取消都要调用完成例程,在完成例程中取消你自己创建的IRP应该是最好的地方 即为你自己的每个新创建IRP的完成例程释放掉自己 |
|
|
30楼#
发布于:2005-02-28 21:14
我用的是IOAllocateIrp.
我看了DDK的例子。都是在IoCancelIrp后等待完成历程执行完毕再继续执行下去。不等待的我没有尝试,现在不作这个了。 创建自己的irp队列也是一样的,照样要在cancelroutine中把没有做的free掉或者cancel掉。 |
|
31楼#
发布于:2005-03-02 10:16
是我在完成历程里又访问了已经释放的内存导致了错误。现在修改已经可以了,谢谢大家的帮助,尤其感谢acidfish与bmyyyud的帮助。
|
|
上一页
下一页