线程 DPC 简介

线程 DPC 在 Windows Vista 和更高版本的 Windows 中可用。

线程 DPC 是系统在 IRQL 处执行的 DPC,等于PASSIVE_LEVEL。 线程 DPC 默认启用,但你可以通过将 HKLM\System\CCS\Control\SessionManager\Kernel\ThreadDpcEnable 注册表项设置为零来禁用它们。 禁用线程 DPC 后,它们将作为普通 DPC 执行。

普通 DPC 会抢占所有线程的执行,并且不能由线程或其他 DPC 抢占。 如果系统有大量普通 DPC 排队,或者其中一个 DPC 长时间运行,则每个线程将任意长时间暂停。 因此,每个普通 DPC 都会增加系统延迟,这可能会损害时间敏感型应用程序(例如音频或视频播放)的性能。

相反,线程 DPC 可由普通 DPC 抢占,但不能被其他线程抢占。 因此,应使用线程式 DPC 而不是普通的 DPC,除非不能抢占特定的 DPC,甚至不能被另一个 DPC 抢占。

系统将线程 DPC (和普通 DPC) 表示为 KDPC 结构。 若要初始化线程 DPC 的 KDPC 结构,请调用 KeInitializeThreadedDpc 例程,并向其传递执行 DPC 操作的 CustomThreadedDpc 例程。

由于 CustomThreadedDpc 例程可以在PASSIVE_LEVEL或DISPATCH_LEVEL执行,因此必须确保 CustomThreadedDpc 例程在两个 IRQL 上正确同步。 有关如何执行此操作的详细信息,请参阅 同步和线程 DPC

此外,必须确保 CustomThreadedDpc 例程遵守DISPATCH_LEVEL代码的所有限制。 如果启用了线程 DPC,则它们在 IRQL = PASSIVE_LEVEL运行,但仍受到与普通 DPC 相同的限制。 在线程 DPC 中执行的所有代码(包括 CustomThreadedDpc 例程调用的所有函数)都必须符合 DPC 环境的限制。 例如,代码不得阻止被动级别同步对象,例如 KEVENT 对象。 许多现有设备堆栈(如网络和 USB)不支持线程 DPC 处理,如果检测到在PASSIVE_LEVEL调用它们,它们可能会尝试阻止。 出于类似原因, 内核模式驱动程序框架 (KMDF) 不支持线程 DPC 处理,KMDF 驱动程序不应尝试使用线程化 DPC。 有关 DPC 环境的详细信息,请参阅 编写 DPC 例程

若要将线程 DPC 添加到 DPC 队列,请调用 KeInsertQueueDpc。 若要在执行队列之前从队列中删除线程 DPC,请调用 KeRemoveQueueDpc