阅读:1477回复:11
关于WDM与WDM之间的同步调用
上层是一个包过滤驱动(NDIS_WDM),下层是一个硬件驱动程序(WDM)。包过滤驱动构造一个IRP,通过IoCallDriver传给我,我又构造一个IRP传给下层硬件驱动程序。硬件驱动程序采用系统队列对我传下的IRP排队,先返回STATUS_PENDING,待中断服务程序完成(调用NextIrp)才返回STATUS_SUCESS。问题是:我希望下层硬件驱动程序在中断处理完成调用IOCOMPLETE(NextIrp)返回我的完成例程后,我才调用IoComplete返回到上层驱动。这就存在一个同步调用问题。请问应该如何实现?三个驱动的IRQL=DISPATCH_LEVEL。
谢谢!!! |
|
|
沙发#
发布于:2002-06-28 09:28
把
pEvent = new (NonPagedPool) KEvent(NotificationEvent, FALSE) ; 放到while的外面看看。 是0x5的错误还是0x50? |
|
板凳#
发布于:2002-06-27 17:16
怎么没有人来回答。zydcat能帮忙吗?
[编辑 - 6/27/02 by hzh6970] |
|
|
地板#
发布于:2002-06-20 14:40
这样呀 我也不太明白是为什么。可能是因为底层驱动的中断是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的错误。 你能否帮我分析以下原因。 谢谢!!!! |
|
|
地下室#
发布于:2002-06-19 17:14
这样呀
那wait怎么会不行呢 |
|
|
5楼#
发布于:2002-06-19 17:05
不明白你的意思 你说方法一般适用应用层对驱动的调用时,驱动程序与驱动程序之间实现同步。而我三层都是驱动程序,首先进行IoCallDriver的是在NDIS_WDM。我用KeGetCurrentIrql得到的IRQL应该不会错。在中间层驱动,对NDIS_WDM传的IRP是在DISPATCH例程里进行处理的。Wait内封装的就是KeWaitForSingleObject,Set封装的是KeSetEvent. |
|
|
6楼#
发布于:2002-06-19 16:22
不明白你的意思
你凭什么说你的驱动的IRQL=DISPATCH_LEVEL 不同的例程是有不同的irql级别的。 还有对于这种封装过的代码我不是很熟, 一般等待事件用KeWaitForSingleObject或KeWaitForMultipleObjects |
|
|
7楼#
发布于:2002-06-19 16:10
使用同步事件可以搞定 :) |
|
|
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 ; } 请问,还有什么好办法? 谢谢!!! |
|
|
9楼#
发布于:2002-06-19 12:44
使用同步事件可以搞定
|
|
|
10楼#
发布于:2002-06-19 12:39
补充:设置完成例程可用IoSetCompletionRoutine
|
|
|
11楼#
发布于:2002-06-19 12:31
上层驱动(NDIS_WDM)为IRP设置一个完成例程,再调用IoCallDriver发送给下一级
|
|
|