hzh6970
驱动牛犊
驱动牛犊
  • 注册日期2001-12-26
  • 最后登录2002-07-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1477回复:11

关于WDM与WDM之间的同步调用

楼主#
更多 发布于:2002-06-19 12:07
上层是一个包过滤驱动(NDIS_WDM),下层是一个硬件驱动程序(WDM)。包过滤驱动构造一个IRP,通过IoCallDriver传给我,我又构造一个IRP传给下层硬件驱动程序。硬件驱动程序采用系统队列对我传下的IRP排队,先返回STATUS_PENDING,待中断服务程序完成(调用NextIrp)才返回STATUS_SUCESS。问题是:我希望下层硬件驱动程序在中断处理完成调用IOCOMPLETE(NextIrp)返回我的完成例程后,我才调用IoComplete返回到上层驱动。这就存在一个同步调用问题。请问应该如何实现?三个驱动的IRQL=DISPATCH_LEVEL。
谢谢!!!
打倒一切反动派。。。。。。
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2002-06-28 09:28

pEvent = new (NonPagedPool) KEvent(NotificationEvent, FALSE) ;
放到while的外面看看。
是0x5的错误还是0x50?
hzh6970
驱动牛犊
驱动牛犊
  • 注册日期2001-12-26
  • 最后登录2002-07-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-06-27 17:16
怎么没有人来回答。zydcat能帮忙吗?


[编辑 -  6/27/02 by  hzh6970]
打倒一切反动派。。。。。。
hzh6970
驱动牛犊
驱动牛犊
  • 注册日期2001-12-26
  • 最后登录2002-07-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-06-20 14:40
这样呀

那wait怎么会不行呢


我也不太明白是为什么。可能是因为底层驱动的中断是DIRQL,会不会使我的事件无效呢?
我又试了一种办法,代码如下:
KEvent e(SynchronizationEvent, FALSE) ;
KEvent* pEvent ;
ULONG   dwCompleteFlag ;

NewIrp.SetCompleteRoutine(IoCompleteRoutine), this, TRUE, TRUE, TRUE) ;
dwCompleteFlag = 0 ;
status = pLowerDevice->IoCallDriver(NewIrp) ;
if( status == STATUS_PENDING )
{
    e.Set() ;
    pEvent->Wait() ;
}

//系统线程,用于检测完成例程是否执行
VOID MyDevice::Thread(void)
{
    LARGE_INTEGER WaitTime ;

    while(TRUE)
    {
        pEvent = new (NonPagedPool) KEvent(NotificationEvent, FALSE) ;
        e.Wait() ;  
        //检测完成标志是否为1
        while( dwCompleteFlag == 0 )
        {
             WaitTime = RtlConvertLongToLargeInteger(500) ;//很奇怪,应该使用负数,表示绝对时间。但使用负数时,无法正常执行。
             KeDelayExecutionThread(KernelMode, FALSE, &WaitTime) ;
        }
        pEvent->Set(IO_NO_INCERMENT, TRUE) ;
        delete pEvent ;
    }
}

NTSTATUS MyDevice::IoCompleteRoutine(KIrp I)
{
    KIrp:eallocate(I) ;
    dwCompleteFlag = 1 ;   //完成后置标志为1
    Return STATUS_MORE_PROCESSING_REQUIRED ;
}
使用上述代码,能够进行工作,但存在稳定性不好的问题,具体表现有:
1、大量调用时,有时会在pEvent->Wait()处出现蓝屏,系统错误为:0x00000005,我不太清楚该错误是由于什么原因产生的。
2、当正常运行时,运行其他应用程序,也会出现0x00000005的错误。
你能否帮我分析以下原因。
谢谢!!!!
打倒一切反动派。。。。。。
zydcat
驱动老牛
驱动老牛
  • 注册日期2001-12-06
  • 最后登录2006-04-12
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-06-19 17:14
这样呀

那wait怎么会不行呢
[color=red]肥虫虫[/color] [img]http://www.driverdevelop.com/forum/upload/bradley/2002-11-15_ig01.gif[/img]
hzh6970
驱动牛犊
驱动牛犊
  • 注册日期2001-12-26
  • 最后登录2002-07-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-06-19 17:05
不明白你的意思

你凭什么说你的驱动的IRQL=DISPATCH_LEVEL

不同的例程是有不同的irql级别的。

还有对于这种封装过的代码我不是很熟,

一般等待事件用KeWaitForSingleObject或KeWaitForMultipleObjects


你说方法一般适用应用层对驱动的调用时,驱动程序与驱动程序之间实现同步。而我三层都是驱动程序,首先进行IoCallDriver的是在NDIS_WDM。我用KeGetCurrentIrql得到的IRQL应该不会错。在中间层驱动,对NDIS_WDM传的IRP是在DISPATCH例程里进行处理的。Wait内封装的就是KeWaitForSingleObject,Set封装的是KeSetEvent.
打倒一切反动派。。。。。。
zydcat
驱动老牛
驱动老牛
  • 注册日期2001-12-06
  • 最后登录2006-04-12
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-06-19 16:22
不明白你的意思

你凭什么说你的驱动的IRQL=DISPATCH_LEVEL

不同的例程是有不同的irql级别的。

还有对于这种封装过的代码我不是很熟,

一般等待事件用KeWaitForSingleObject或KeWaitForMultipleObjects
[color=red]肥虫虫[/color] [img]http://www.driverdevelop.com/forum/upload/bradley/2002-11-15_ig01.gif[/img]
magicx
驱动老牛
驱动老牛
  • 注册日期2002-02-22
  • 最后登录2014-08-18
  • 粉丝1
  • 关注0
  • 积分-14分
  • 威望13点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-06-19 16:10
使用同步事件可以搞定


 :)
[color=red]大头鬼! :P[/color]
hzh6970
驱动牛犊
驱动牛犊
  • 注册日期2001-12-26
  • 最后登录2002-07-21
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-06-19 15:44
使用同步事件可以搞定


谢谢你的回答。你说的方法我试过,但不行。
首先,KEvent的初始化必须在PASSIVE_LEVEL,而我的IRQL=DISPATCH_LEVEL。如果使用事件,只能在设备的构造函数里实现。
其次,在我的代码如中:
context.e = event ;
NewIrp.SetCompleteRoutine(IoCompleteRoutine), &context, TRUE, TRUE, TRUE) ;
status = pLowerDevice->IoCallDriver(NewIrp) ;
if( status == STATUS_PENDING )
{
    event.Wait() ;   //此时,Wait不能够停住!!!
}

NTSTATUS MyDevice::IoCompleteRoutine(KIrp I, Context* pContext)
{
    KIrp::Deallocate(I) ;
    pContext->e.Set() ;

    Return STATUS_MORE_PROCESSING_REQUIRED ;
}

请问,还有什么好办法?
谢谢!!!

打倒一切反动派。。。。。。
zydcat
驱动老牛
驱动老牛
  • 注册日期2001-12-06
  • 最后登录2006-04-12
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-06-19 12:44
使用同步事件可以搞定
[color=red]肥虫虫[/color] [img]http://www.driverdevelop.com/forum/upload/bradley/2002-11-15_ig01.gif[/img]
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
10楼#
发布于:2002-06-19 12:39
补充:设置完成例程可用IoSetCompletionRoutine
八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
11楼#
发布于:2002-06-19 12:31
上层驱动(NDIS_WDM)为IRP设置一个完成例程,再调用IoCallDriver发送给下一级
八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
游客

返回顶部