阅读:2720回复:7
请教系统线程退出时的IRP取消问题
我的驱动程序创建开了一个系统线程,在线程中通过在一个循环调用IoBuildSynchronousFsdRequest()和IoBuildDeviceIoControlRequest()创建IRP发送给下层的USB驱动程序来读写数据,然后通过KeWaitForMultipleObjects()等待事件(其中有一个是“线程终止”事件,如果该事件被触发,则从循环中退出并退出系统线程),现在碰到了以下现象:
在我的驱动程序卸载以后,如果再卸载下层USB驱动程序,则系统崩溃。 我怀疑在我的线程退出时,对于那些在线程中创建并发往下层的尚未完成的IRP, IO管理器并没有发送IoCancelIrp(Irp)来取消它们,是不是必须在退出线程前由自己来取消它们?如果是需要自己来取消,有没有什么比较好的办法来实现? 请高手帮助。谢谢。 |
|
最新喜欢:![]() |
沙发#
发布于:2001-07-19 13:39
要不要自己取消呢,我就不知道,但是,如果需要自己取消的话,已经有一篇帖子讲的很详细了。是“海云居士”发的帖子,你收一下就得了。
|
|
|
板凳#
发布于:2001-07-19 13:44
|
|
|
地板#
发布于:2001-07-19 14:17
谢谢,我看了一下“海云居士”发的帖子,其解决方法是采用WaltOney的书中所介绍的挂接完成例程,然后在超时等待中自己去做IoCancelIrp(), 这种方法虽然是可靠的,但是与我的情况有些不一样:
1. 由于何时能从下层USB读到数据是不确定的,完全取决于对方是否发送了数据过来.所以采用超时等待是不行的. 2. 我没有挂接自己的完成例程, IRP依靠IO管理器完成后自动清除, 这样处理起来比较简单. 3. 系统线程必须采用KeWaitforMultiObject()来等待多个信号量,其中最后一个信号量是“线程终止”事件,由其它线程触发(例如调用Unload例程的线程),当我创建的系统线程获得此"线程终止"事件后,从循环中退出,但是此时判断当前还有哪些IRP未完成比较困难(“线程终止”事件触发时读写IRP可能也刚好同时完成,或读完成写未完成,或读写均未完成,等等)。 我现在需要确认 死机现象是否确实是由这些未完成的IRP所造成的? 如果是, 有没有一种不需要挂接完成例程的方法来解决此问题? [mym 编辑于 2001-07-25 11:43] |
|
地下室#
发布于:2001-07-25 14:27
请高手帮忙回答一下,谢谢。
|
|
5楼#
发布于:2001-07-25 15:58
驱动程序在卸载时,如有未被completed的irp,可以在此驱动cleanup例程里将此排队的(queued)irp取消。不知代码细节,不敢妄言。
|
|
6楼#
发布于:2001-07-26 18:30
通过实验,我现在已基本搞清了原因. 与大家交流
1.普通WIN32用户态程序与驱动程序交互: (1).当用户程序打开设备时, IO管理器向驱动程序发IRP_MJ_CREATE. (2) 用户程序退出时,不论此时是否有未完成的IRP, IO管理器都会首先向驱动发IRP_MJ_CLEANUP. (3) 如果在发送了IRP_MJ_CLEANUP之后,仍有未完成的IRP(例如驱动程序未提供CleanUp例程或在CleanUp例程中未清除所有未完成的IRP,就会造成这种情况), 则IO管理器会依次调用这些IRP的OnCancel例程(如果驱动程序既未提供CleanUp例程又未挂接Cancel例程就糟了,这些IRP将无法得到清除).最后,IO管理器向驱动发IRP_MJ_CLOSE. 2.上层驱动程序与下层驱动程序的交互. (1).当上层驱动调用IoGetDeviceObjectPointer()时,该函数会向下层驱动发送IRP_MJ_CREATE和IRP_MJ_CLEANUP. (2).当上层驱动调用ObDereferenceObject()时,该函数只会向下层驱动发送IRP_MJ_CLOSE. 3.故障原因: 我的上层驱动在Unload例程中调用了ObDereferenceObject(), 但是由于仍有未完成的IRP,因此即使我的上层驱动卸载了,但这些IRP仍然留在下层驱动程序的队列中未得到清除,以后当下层驱动一旦去完成这些IRP时就会造成BUG_CHECK, 因为IRP中的FileObject域指的文件对象已不存在. |
|
7楼#
发布于:2001-07-27 08:45
分析透彻!一般的驱动都要注册并实现CLEANUP的dispatch.
|
|