蓝屏后用windbg打开dump 发现KeRemoveEntryDeviceQueue引发蓝屏 不知道怎么解决 大家帮忙看看 谢谢
如果在应用程序中不调用CancelIo 则不会引发蓝屏
这个程序大致情况是这样:应用程序创建2个线程 两个线程函数是一样的 都是readFile 然后read是异步的 read以后就是 CancelIo 然后是等待
驱动程序里边 对IRP进行了队列化
驱动代码如下:
#pragma LOCKEDCODE
VOID MyStartIo( IN PDEVICE_OBJECT DeviceObject,IN PIRP pFistIrp)
{
KdPrint(("Enter MyStartIo\n"));
KIRQL oldirql;
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
DeviceObject->DeviceExtension;
PKDEVICE_QUEUE_ENTRY device_entry;
//获取cancel自旋锁
IoAcquireCancelSpinLock(&oldirql);
if(pFirstIrp!=pDevExt->pCurrentIRP||pFirstIrp->Cancel)
{
IoReleaseCancelSpinLock(oldirql);
return;
}else
{
IoSetCancelRoutine(pFirstIrp, NULL);
IoReleaseCancelSpinLock(oldirql);
}
PIRP Irp = pFistIrp;
do
{
KEVENT event;
KeInitializeEvent(&event,NotificationEvent,FALSE);
//等3秒
LARGE_INTEGER timeout;
timeout.QuadPart = -3*1000*1000*10;
//定义一个3秒的延时,主要是为了模拟该IRP操作需要大概3秒左右时间
KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,&timeout);
KdPrint(("Complete a irp:%x\n",Irp));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // no bytes xfered
IoCompleteRequest(Irp,IO_NO_INCREMENT);
device_entry=KeRemoveDeviceQueue(&pDevExt->device_queue);
KdPrint(("device_entry:%x\n",device_entry));
if (device_entry==NULL)
{
break;
}
Irp = CONTAINING_RECORD(device_entry, IRP, Tail.Overlay.DeviceQueueEntry);
}while(1);
KdPrint(("Leave MyStartIo\n"));
}
VOID OnCancelIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
KdPrint(("Enter CancelReadIRP\n"));
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
if(pdx->pCurrentIRP == Irp)
{
//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);
//从IRP队列取出下一个IRP 并将它送给startIO
IoStartNextPacket(DeviceObject, TRUE);
KeLowerIrql(Irp->CancelIrql);
}else
{
//把IRP从队列中删除 但是并不影响IRP 本身
KeRemoveEntryDeviceQueue(&pdx->device_queue, &Irp->Tail.Overlay.DeviceQueueEntry);
//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);
}
//设置完成状态为STATUS_CANCELLED
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );
KdPrint(("Leave CancelReadIRP\n"));
}
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
KdPrint(("Enter HelloDDKRead\n"));
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;
//将IRP设置为挂起
IoMarkIrpPending(pIrp);
IoSetCancelRoutine(pIrp,OnCancelIRP);
KIRQL oldirql;
//提升IRP至DISPATCH_LEVEL
KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
KdPrint(("HelloDDKRead irp :%x\n",pIrp));
KdPrint(("DeviceQueueEntry:%x\n",&pIrp->Tail.Overlay.DeviceQueueEntry));
if (!KeInsertDeviceQueue(&pDevExt->device_queue, &pIrp->Tail.Overlay.DeviceQueueEntry))
MyStartIo(pDevObj,pIrp);
//将IRP降至原来IRQL
KeLowerIrql(oldirql);
KdPrint(("Leave HelloDDKRead\n"));
//返回pending状态
return STATUS_PENDING;
}
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status;
//设置卸载函数 设置派遣函数 创建驱动设备对象
return status;
}
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)