windows 内核system worker threads

在编写windows驱动的时候,我们需要关心两个中断级别(IRQL),PASSIVE_LEVEL(0)和DISPATCH_LEVEL(2)。windows大部分的时间,都运行在0-2级别,当设备中断来临时,windows会将IRQL提升至硬件中断级别(DIRQL, DEVICE INTERRUPT REQUEST LEVEL),并且运行相应的硬件中断处理函数。当硬件中断结束后,恢复到原来的IRQL。
用户模式的代码是运行在最低级别的PASSIVE_LEVEL中,驱动程序的DriverEntry函数,派遣函数,AddDevice函数一般运行在PASSIVE_LEVEL中(驱动程序的StartIO和DPC函数运行在DISPATCH_LEVEL中),它们在必要的时候可以申请进入DISPATCH_LEVEL级别,使用内核函数KeGetCurrentIrql()可以知道系统的当前IRQL。

Windows负责线程调度的组件运行在DISPATCH_LEVEL级别,当前线程运行完时间片后,操作系统自动从PASSIVE_LEVEL提升至DISPATCH_LEVEL级别,从而可以使得线程调度组件可以调度其他的线程。当线程切换完成后,操作系统又从DISPATCH_LEVEL级别恢复到PASSIVE_LEVEL级别。

有时候,锁会提升程序的IRQL。比如说从0(PASSIVE_LEVEL)提升到了DISPATCH_LEVEL中,这就会导致有的api使用不了

使用system worker threads可以解决这个问题

WorkItem能排队注册的回调函数, 当例程处于DISPATCH_LEVEL(2)级别时将回调函数塞入队列,当进程降低到PASSIVE_LEVEL(0)时,这些队列中的回调函数将会被系统调用。
注意事项:
而且根据CSDN的介绍,工作队列有两个需要注意的地方。一是不能执行太长的操作,会死锁。2是在排队工作项之前,最好释放所有的mutex、lock、semaphore,否则很容易死锁。
反正这两种操作都不错(另一种线程的方法参见前面文档)。随便选一个用用就行了。

官方文档

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/system-worker-threads

大概翻译:
当你需要driver延迟执行某些动作的时候,可以使用work item。driver可以把这些work item入队。windows系统维护了一个线程池,线程会从队列中取出来一个work item,并执行他的回掉routine, 并且从队列中删除它。

To use a work item, a driver performs the following steps:

  1. Allocate and initialize a new work item.(IoAllocateWorkItem)
    2.关联一个回掉历程。([IoQueueWorkItem])
  2. 释放。( IoFreeWorkItem

代码片段

PIO_WORKITEM pIoWorkItem;
pIoWorkItem = IoAllocateWorkItem(device);
if (pIoWorkItem)
        {
            IoQueueWorkItem(pIoWorkItem, CallBack, DelayedWorkQueue, NULL);
            IoFreeWorkItem(pIoWorkItem);
        }

你可能感兴趣的:(windows 内核system worker threads)