windows驱动WorkItem
|
我之前写过一篇文章:https://blog.csdn.net/dailongjian2008/article/details/78621980,讲述如何解决在DISPATCH_LEVEL下读写文件的问题,我当时的做法是将IRQL强行降至PASSIVE_LEVEL,虽然软件发布后运行一直稳定,此处没有出现过任何问题,但是总感觉不是很安心,因为是采用强制的方式,会不会影响其他层面的调度却是一个未知数。 接下来还有一种方式能解决这样的问题,就是WorkItem的方式,windows系统会执行一个Worker线程,该线程会不断从Worker队列中取出任务然后执行,执行是在PASSIVE_LEVEL下的,所以我们可以将我们要进行的文件操作作为一个WorkerItem放入Worker队列中,以下是我在IoControl中执行设置EDID的操作,该操作需要在PASSIVE_LEVEL下执行。 static NTSTATUS HandleIoControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(pIrp);
KIRQL OldIrql;
if (irpsp->MajorFunction != IRP_MJ_DEVICE_CONTROL) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
PIO_WORKITEM pIoWorkItem = IoAllocateWorkItem(pDevObj);
if (pIoWorkItem == nullptr) {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
KeAcquireSpinLock(&g_lock,&OldIrql);
IoInitializeWorkItem(pDevObj,pIoWorkItem);
IoQueueWorkItemEx(pIoWorkItem,(PIO_WORKITEM_ROUTINE_EX)DoIocontrol,DelayedWorkQueue,pIrp);
IoMarkIrpPending(pIrp);
KeReleaseSpinLock(&g_lock,OldIrql);
return STATUS_PENDING;
}
其中 DoIoControl是Worker线程要执行的任务,pIrp是传递给DoIoControl的一个参数,该参数类型可自定义。看下DoIoControl的实现: static VOID DoIocontrol(IN PDEVICE_OBJECT DeviceObject,PIRP pIrp,PIO_WORKITEM IoWorkItem)
{
UNREFERENCED_PARAMETER(DeviceObject);
KIRQL OldIrql;
KeAcquireSpinLock(&g_lock,&OldIrql);
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(pIrp);
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = status;
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_SET_CUSTOM_EDID:
{
ULONG uInputLength = irpsp->Parameters.DeviceIoControl.InputBufferLength;
BYTE *inputBuffer = (BYTE *)pIrp->AssociatedIrp.SystemBuffer;
if (uInputLength >= MIN_EDID_LENGTH
&& pHwDeviceExtension != nullptr
&& pHwDeviceExtension->pMonitor != nullptr) {
pHwDeviceExtension->pMonitor->SetEdid(inputBuffer,uInputLength);
}
else {
status = STATUS_INVALID_VARIANT;
}
break;
}
default:
break;
}
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
IoUninitializeWorkItem(IoWorkItem);
IoFreeWorkItem(IoWorkItem);
KeReleaseSpinLock(&g_lock,OldIrql);
}上述代码加了一个自旋锁,是由于多了一个worker线程,为防止在DoIoControl中先将IRP完成了,然后再在HandleIoControl中执行IoMarkIrpPending(pIrp);造成蓝屏,所以当前的逻辑确保在HandleIoControl中执行IoMarkIrpPending(pIrp);后再执行Worker队列中的任务。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- typescript – 错误:在尝试扩展tslint-microsof
- 第二阶段团队绩效考核报告
- windows – 有什么方法可以在Vista X64上本地播放
- windows-server-2012 – Windows Server 2012故障
- LoadLibrary project.dll失败.指定的模块无法找到
- 当中央存储库位于Windows文件共享上时,对多个用户
- 目录 – NTFS连接与符号链接(用于目录)[已关闭]
- wix – 为什么在使用MSI时限制文件部署到用户配置
- winapi – Windows Aero – 以编程方式禁用视觉效
- windows-server-2008 – Sharepoint的免费版本是
