mym
mym
驱动牛犊
驱动牛犊
  • 注册日期2001-06-20
  • 最后登录2002-06-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2721回复:7

请教系统线程退出时的IRP取消问题

楼主#
更多 发布于:2001-07-19 13:16
我的驱动程序创建开了一个系统线程,在线程中通过在一个循环调用IoBuildSynchronousFsdRequest()和IoBuildDeviceIoControlRequest()创建IRP发送给下层的USB驱动程序来读写数据,然后通过KeWaitForMultipleObjects()等待事件(其中有一个是“线程终止”事件,如果该事件被触发,则从循环中退出并退出系统线程),现在碰到了以下现象:
在我的驱动程序卸载以后,如果再卸载下层USB驱动程序,则系统崩溃。
我怀疑在我的线程退出时,对于那些在线程中创建并发往下层的尚未完成的IRP, IO管理器并没有发送IoCancelIrp(Irp)来取消它们,是不是必须在退出线程前由自己来取消它们?如果是需要自己来取消,有没有什么比较好的办法来实现?

请高手帮助。谢谢。

最新喜欢:

hbnhbnhbnhbnhbn...
KDriver
驱动中牛
驱动中牛
  • 注册日期2001-06-09
  • 最后登录2008-09-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2001-07-19 13:39
要不要自己取消呢,我就不知道,但是,如果需要自己取消的话,已经有一篇帖子讲的很详细了。是“海云居士”发的帖子,你收一下就得了。
“萎软”,是Microsoft的小名!
KDriver
驱动中牛
驱动中牛
  • 注册日期2001-06-09
  • 最后登录2008-09-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2001-07-19 13:44
“萎软”,是Microsoft的小名!
mym
mym
驱动牛犊
驱动牛犊
  • 注册日期2001-06-20
  • 最后登录2002-06-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2001-07-19 14:17
谢谢,我看了一下“海云居士”发的帖子,其解决方法是采用WaltOney的书中所介绍的挂接完成例程,然后在超时等待中自己去做IoCancelIrp(), 这种方法虽然是可靠的,但是与我的情况有些不一样:
 1. 由于何时能从下层USB读到数据是不确定的,完全取决于对方是否发送了数据过来.所以采用超时等待是不行的.
 2. 我没有挂接自己的完成例程, IRP依靠IO管理器完成后自动清除, 这样处理起来比较简单.
 3. 系统线程必须采用KeWaitforMultiObject()来等待多个信号量,其中最后一个信号量是“线程终止”事件,由其它线程触发(例如调用Unload例程的线程),当我创建的系统线程获得此"线程终止"事件后,从循环中退出,但是此时判断当前还有哪些IRP未完成比较困难(“线程终止”事件触发时读写IRP可能也刚好同时完成,或读完成写未完成,或读写均未完成,等等)。

我现在需要确认 死机现象是否确实是由这些未完成的IRP所造成的?
如果是, 有没有一种不需要挂接完成例程的方法来解决此问题?


[mym 编辑于 2001-07-25 11:43]
mym
mym
驱动牛犊
驱动牛犊
  • 注册日期2001-06-20
  • 最后登录2002-06-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2001-07-25 14:27
请高手帮忙回答一下,谢谢。
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2001-07-25 15:58
驱动程序在卸载时,如有未被completed的irp,可以在此驱动cleanup例程里将此排队的(queued)irp取消。不知代码细节,不敢妄言。
mym
mym
驱动牛犊
驱动牛犊
  • 注册日期2001-06-20
  • 最后登录2002-06-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
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域指的文件对象已不存在.


  
dazzy
驱动中牛
驱动中牛
  • 注册日期2001-03-23
  • 最后登录2008-08-12
  • 粉丝1
  • 关注0
  • 积分0分
  • 威望10点
  • 贡献值1点
  • 好评度10点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2001-07-27 08:45
分析透彻!一般的驱动都要注册并实现CLEANUP的dispatch.
游客

返回顶部