阅读:3277回复:31
app异常结束的时候,驱动里如何完成已经挂起或尚未完成的irp?
驱动中接受app得读请求,然后自己创建irp,注册完成例程,并把它发送给总线驱动,如果此irp尚未完成,此时app被异常结束(如结束任务)了,那我在驱动中应该如何处理irp呢?
如果是用计时器,在dpc例程中取消掉这个irp,然后等待。此时会进入完成例程,等到完成例程处理完毕,在设置事件。现在的问题是: dpc例程运行在dispatch_level上,在这个irql上不能等待。 告诉我一个可行的方法把,谢谢先了。 异步读写一定会碰到这个问题吧,大家都是怎么解决的呢? [编辑 - 2/5/05 by xiaorain] |
|
最新喜欢:Zhouy |
沙发#
发布于:2005-02-05 17:15
注册CancelRountion
|
|
|
板凳#
发布于:2005-02-05 17:43
注册CancelRountion 好像比较麻烦的 |
|
|
地板#
发布于:2005-02-06 09:41
[quote]注册CancelRountion 好像比较麻烦的 [/quote] 为什么??? |
|
|
地下室#
发布于:2005-02-06 15:03
怎么个注册法!
|
|
5楼#
发布于:2005-02-07 09:59
驱动中接受app得读请求,然后自己创建irp,注册完成例程,并把它发送给总线驱动,如果此irp尚未完成,此时app被异常结束(如结束任务)了,那我在驱动中应该如何处理irp呢? 在DPC中创建一个核心线程专门处理此事就可以了。 |
|
|
6楼#
发布于:2005-02-21 09:13
cancelroutine是下层驱动在取消IRP或者应用程序调用CancelIo的时候才会被调用吧。
现在如果应用程序被结束任务了,应用程序不会调用cancelIo了,要想取消IRP,只能是下层驱动取消irp,然后上层驱动的cancelroutine才会被调用了。 下层驱动如何知道要取消Irp呢?我在驱动中设置了cancelroutine,在应用程序被结束任务的时候,cancelroutine没有被调用。 |
|
7楼#
发布于:2005-02-21 09:58
或者,用个定时器检测超时,用CustomTimerDpc处理吧
|
|
|
8楼#
发布于:2005-02-21 10:15
这种情况,我前段时间专门试验过。
当应用层某一个线程发送到驱动的Irp没有返回,就是说驱动IoMarkIrpPending,return STATUS_PENDING,这种情况下,若该线程步进行等待而要直接完成退出,那么该线程结束代码会要求I/O manager调用该Irp的cancel routien(如果有的话)。如果驱动中没有为该Irp设置cancel routine,那么该线程不会结束。 所以对于有可能无限期完成的Irp,最好设置cancel routine。当然如果你驱动中有一个定时器,定时对pending的Irp完成的话,就完全没有必要设置cancel routine.这段话DDK里边详细提过。 现在ddk提供了新的cancel routine的处理方法,CSQ。详细的清参考IoCsqInitialize等函数。 |
|
9楼#
发布于:2005-02-21 10:19
驱动中接受app得读请求,然后自己创建irp,注册完成例程,并把它发送给总线驱动,如果此irp尚未完成,此时app被异常结束(如结束任务)了,那我在驱动中应该如何处理irp呢? 刚刚看到,如果是自己创建的Irp,那么肯定要自己负责调用IoCancelIrp来cancel这个自己创建的Irp了。 |
|
10楼#
发布于:2005-02-21 11:23
或者,用个定时器检测超时,用CustomTimerDpc处理吧 这种方法对于自己创建的irp好像不可行。 我测试过,customerTimerDpc运行在dispatch_level上,在这个中断级上,不能等待。而如果我在customerTimerDpc中用IoCancelIrp取消自己创建的irp,此时立即就会进入此irp地完成例程,这样的话,我在customerTimerDpc中就要等待了,直到完成例程执行完毕。而在dispatch_level上是没法子等待的。 |
|
11楼#
发布于:2005-02-22 10:58
[quote]或者,用个定时器检测超时,用CustomTimerDpc处理吧 这种方法对于自己创建的irp好像不可行。 我测试过,customerTimerDpc运行在dispatch_level上,在这个中断级上,不能等待。而如果我在customerTimerDpc中用IoCancelIrp取消自己创建的irp,此时立即就会进入此irp地完成例程,这样的话,我在customerTimerDpc中就要等待了,直到完成例程执行完毕。而在dispatch_level上是没法子等待的。 [/quote] 下次customerTimerDpc中再处理不行吗? |
|
|
12楼#
发布于:2005-02-22 11:25
[quote][quote]或者,用个定时器检测超时,用CustomTimerDpc处理吧 这种方法对于自己创建的irp好像不可行。 我测试过,customerTimerDpc运行在dispatch_level上,在这个中断级上,不能等待。而如果我在customerTimerDpc中用IoCancelIrp取消自己创建的irp,此时立即就会进入此irp地完成例程,这样的话,我在customerTimerDpc中就要等待了,直到完成例程执行完毕。而在dispatch_level上是没法子等待的。 [/quote] 下次customerTimerDpc中再处理不行吗? [/quote] 能详细说明一下吗? 我今天用了cancelroutine,也是不行,cancelroutine 运行在dispatch_level上。 |
|
13楼#
发布于:2005-02-22 11:48
在取消例程中设置变量表明取消,不过我总觉得哪里出问题了,办法太笨。也许看看WINDDK\\2600.1106\\src\\general\\cancel有用,我也得先好好看看
|
|
|
14楼#
发布于:2005-02-22 12:07
今天发现结束任务的时候,如果还有irp没有完成,应用无法结束,总是剩下一个线程。但是过了几分钟后,系统会发送IRP_MJ_CLEANUP的irp,然后我在clean例程中结束irp,应用结束了。
不知道大家以前又没有发现这样的现象? |
|
15楼#
发布于:2005-02-22 15:16
想了想,为什么不在customerTimerDpc用代码直接取消irp,为什么要调用取消例程再等待呢?Copy/Paste再用些互斥手段不可以吗?
|
|
|
16楼#
发布于:2005-02-22 16:16
今天发现结束任务的时候,如果还有irp没有完成,应用无法结束,总是剩下一个线程。但是过了几分钟后,系统会发送IRP_MJ_CLEANUP的irp,然后我在clean例程中结束irp,应用结束了。 参看9楼acidfish大哥的办法,应用程序结束的时候会收到IRP_MJ_CLOSE的,处理这个的时候调用IoCancelIrp把等待的irp(必须是自己创建的)结束掉就可以了。 好象是要几分钟以后,那个剩下的内核线程会被os杀掉。 |
|
17楼#
发布于:2005-02-22 17:07
想了想,为什么不在customerTimerDpc用代码直接取消irp,为什么要调用取消例程再等待呢?Copy/Paste再用些互斥手段不可以吗? 因为自己构造了irp,在取消系统发来的irp的时候,要cancel掉自己构造的irp。而如果cancel自己构造的irp的话,调用IoCancelIrp()后,就会进入完成例程,待到完成例程执行完毕后,再继续执行,所以需要等待,而在customtimerdpc是运行在dispatch_level上的,所以无法等待。 |
|
18楼#
发布于:2005-02-22 17:17
[quote]今天发现结束任务的时候,如果还有irp没有完成,应用无法结束,总是剩下一个线程。但是过了几分钟后,系统会发送IRP_MJ_CLEANUP的irp,然后我在clean例程中结束irp,应用结束了。 参看9楼acidfish大哥的办法,应用程序结束的时候会收到IRP_MJ_CLOSE的,处理这个的时候调用IoCancelIrp把等待的irp(必须是自己创建的)结束掉就可以了。 好象是要几分钟以后,那个剩下的内核线程会被os杀掉。 [/quote] 我感觉应用程序异常结束,如从任务管理器中结束任务,os不会立即发送IRp_mj_cleanup,而是要过一段时间,如几分钟再发送,此时内核线程就被结束了。 从任务管理器中结束任务的时候,如果设置了cancelroutine,则cancelroutine将立即被调用,但是I在cancelroutine中调用IoCancelIrp取消自己创建的irp有风险,因为调用IoCancelIrp()后,会进入自己创建的irp地完成例程,这样在cancelroutine()中就需要等待,而cancelroutine是运行在dispatch_level的。 我尝试了在cancelroutine中等待,每次都是蓝屏(driver_irql_not_less_or_equal). |
|
19楼#
发布于:2005-02-22 20:43
Cancel例程是不需要等待的,在你自己的完成例程里面置上一个事件,然后再Passiv_level上等待那个事件不就可以了。IoCancelRoutine不是在CancelRoutine里调用的。
// Cancel routine VOID CancelTestIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; Test_KdPrint((\"CancelTestIrp, Irp = 0x%08X\\n\", Irp)); IoReleaseCancelSpinLock(Irp->CancelIrql); CompleteRequest(Irp, STATUS_CANCELLED, 0); } |
|
上一页
下一页