Поделиться через


Рекомендации по написанию процедур DPC

При написании подпрограммы DpcForIsr или CustomDpc учитывайте следующие моменты:

  • Подпрограмма DpcForIsr или CustomDpc должна синхронизировать свой доступ к физическому устройству и любым общим сведениям о состоянии или ресурсам, которые поддерживает драйвер, с другими подпрограммами драйвера, которые обращаются к тому же устройству или памяти.

    Если подпрограмма DpcForIsr или CustomDpc совместно использует устройство или состояние с ISR, она должна вызвать KeSynchronizeExecution, указав адрес предоставленной драйвером подпрограммы SynchCritSection , которая программирует устройство или обращается к общему состоянию. Дополнительные сведения см. в разделе Использование критических разделов.

    Если подпрограмма DpcForIsr или CustomDpc совместно использует состояние или ресурсы, такие как заблокированная очередь или объект таймера, с подпрограммами, отличными от ISR, она должна защищать общее состояние или ресурсы с помощью инициализированного драйвера исполнительной спин-блокировки. Дополнительные сведения см. в разделе Spin Locks.

  • Подпрограммы DpcForIsr и CustomDpc выполняются в среде IRQL = DISPATCH_LEVEL, что ограничивает набор процедур поддержки, которые они могут вызывать.

    Например, подпрограммы DpcForIsr и CustomDpc не могут получать доступ к памяти и выделять их, а также не могут ждать, пока объекты диспетчера ядра будут настроены в состояние сигнала. С другой стороны, они могут получить и освободить спин-блокировку руководителя драйвера с помощью KeAcquireSpinLockAtDpcLevel и KeReleaseSpinLockFromDpcLevel, которые работают быстрее, чем KeAcquireSpinLock и KeReleaseSpinLock.

    Хотя подпрограмма DPC не может выполнять блокирующие вызовы, она может ставить рабочий элемент в очередь для выполнения в системном рабочем потоке , который выполняется в IRQL, равном PASSIVE_LEVEL. Рабочий элемент может выполнять блокирующие вызовы, ожидающие объектов диспетчера. Чтобы поместить рабочий элемент в очередь, подпрограмма DpcForIsr обычно вызывает подпрограмму, например IoQueueWorkItem, а подпрограмма CustomDpc обычно вызывает подпрограмму ExQueueWorkItem .

  • Подпрограммы DpcForIsr и CustomDpc обычно отвечают за запуск следующей операции ввода-вывода на устройстве.

    Для драйверов низкоуровневых физических устройств, использующих прямой ввод-вывод, эта ответственность может включать использование процедуры SynchCritSection , чтобы запрограммировать устройство для передачи дополнительных данных для удовлетворения текущего IRP, прежде чем драйвер вызовет IoStartNextPacket.

  • Подпрограммы DpcForIsr и CustomDpc должны выполняться только в течение кратковременных периодов и должны делегировать как можно больше обработки рабочим потокам.

    Хотя подпрограмма DPC выполняется на процессоре, все потоки не могут работать на одном процессоре. Другие подпрограммы DPC, которые поставлены в очередь и готовы к выполнению, могут быть заблокированы до завершения текущей подпрограммы DPC. Чтобы избежать снижения скорости отклика системы, типичная подпрограмма DPC должна выполняться не более 100 микросекунд при каждом вызове. Если задача требует более 100 микросекунд и должна выполняться в IRQL, равном DISPATCH_LEVEL, то подпрограмма DPC должна завершиться через 100 микросекунд и запланировать выполнение одной или нескольких подпрограмм CustomTimerDpc для выполнения задачи позже. Дополнительные сведения о подпрограммах CustomTimerDpc см. в разделе Объекты таймера и DPC.

    Подпрограмма DPC должна выполнять только задачи, которые должны выполняться в DISPATCH_LEVEL, а затем делегировать все оставшиеся работы, связанные с прерываниями, потокам, которые выполняются в IRQL = PASSIVE_LEVEL. Например, подпрограмма DPC может ставить рабочий элемент в очередь для выполнения в системном рабочем потоке.

    Подпрограммы DPC, вызывающие подпрограмму KeStallExecutionProcessor для задержки выполнения, не должны указывать задержки более 100 микросекунд.

    Используйте средства анализа производительности в WDK для оценки времени выполнения подпрограмм DPC. Пример использования средства tracelog для отслеживания времени выполнения DPC см. в примере 15. Измерение времени DPC/ISR.

  • Если драйвер использует DMA и его подпрограмма AdapterControl возвращает KeepObject или DeallocateObjectKeepRegisters (тем самым сохраняя системный канал контроллера DMA или адаптер master шины для дополнительных операций передачи), подпрограмма DpcForIsr или CustomDpc отвечает за освобождение объекта адаптера или регистров карты с помощью FreeAdapterChannel или FreeMapRegisters. перед завершением текущего IRP и возвратом управления.

  • Если драйвер низкоуровневого физического устройства настраивает объект контроллера для синхронизации операций ввода-вывода через контроллер с подключенными устройствами, его подпрограмма DpcForIsr или CustomDpc отвечает за освобождение объекта контроллера с помощью IoFreeController до завершения текущего IRP и возврата управления.

  • Подпрограммы DpcForIsr и CustomDpc обычно отвечают за ведение журнала ошибок устройства, возникших во время обработки данного запроса, повторную попытку текущего запроса, если это возможно, а также за настройку блока состояния ввода-вывода и вызов IoCompleteRequest для текущего IRP.

  • Если драйвер и устройство поддерживают перекрывающиеся операции ввода-вывода, драйвер должен следовать правилам обработки перекрывающихся операций ввода-вывода.

  • Подпрограмма DpcForIsr или CustomDpc любого драйвера обычно завершает обработку ввода-вывода только для подмножества общедоступных кодов управления вводом-выводом, которые должен поддерживать драйвер. В частности, подпрограмма DPC выполняет операции для запросов управления устройствами со следующими характеристиками:

    • Запросы, изменяющие состояние физического устройства

    • Запросы, требующие возврата непостоянной информации о физическом устройстве