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


Написание ISR

Драйверы для физических устройств, создающих прерывания, должны иметь по крайней мере одну подпрограмму обслуживания прерываний (ISR). ISR должен выполнить все действия, соответствующие устройству, чтобы закрыть прерывание, в том числе, возможно, остановить прерывание устройства. Затем он должен выполнять только то, что необходимо для сохранения состояния и постановки DPC в очередь для завершения операции ввода-вывода с более низким приоритетом (IRQL), чем тот, при котором выполняется ISR.

IsR драйвера выполняется в контексте прерывания в некотором назначаемом системой DIRQL, как указано в параметре SynchronizeIrql для IoConnectInterruptEx.

ISR могут быть прерваны. Другое устройство с более высоким назначаемого системой DIRQL может прервать работу, или может произойти прерывание системы с высоким уровнем IRQL в любое время.

Прежде чем система вызовет ISR, она получает блокировку спина прерывания, поэтому ISR не может одновременно выполняться на другом процессоре. После возврата ISR система освобождает спин-блокировку.

Так как ISR выполняется на относительно высоком уровне IRQL, который маскирует прерывания с эквивалентным или более низким ЗНАЧЕНИЕм IRQL на текущем процессоре, он должен возвращать управление как можно быстрее. Кроме того, запуск ISR в DIRQL ограничивает набор процедур поддержки, которые может вызывать ISR. Дополнительные сведения см. в разделе Управление приоритетами оборудования.

Как правило, ISR выполняет следующие общие действия.

  • Если устройство, вызвавшее прерывание, не поддерживается ISR, ISR немедленно возвращает значение FALSE.

  • В противном случае ISR очищает прерывание при необходимости, сохраняя необходимый контекст устройства, и помещает DPC в очередь для завершения операции ввода-вывода на более низком уровне IRQL. Дополнительные сведения см. в разделе Объекты DPC и DPC . После этого ISR должен возвращать ЗНАЧЕНИЕ TRUE.

В частности, в драйверах, которые не перекрывают операции ввода-вывода устройства, ISR должен выполнять следующие действия:

  1. Определите, является ли прерывание фиктивным. Если это так, немедленно верните значение FALSE , чтобы isr устройства, которое прервалось, был немедленно вызван. В противном случае продолжите обработку прерываний.

  2. При необходимости остановите прерывание устройства.

  3. Соберите все сведения о контексте, необходимые подпрограмме DpcForIsr (или CustomDpc) для завершения обработки ввода-вывода для текущей операции.

  4. Храните этот контекст в области, доступной подпрограмме DpcForIsr или CustomDpc , обычно в расширении устройства целевого объекта устройства, для которого обработка текущего запроса ввода-вывода вызвала прерывание.

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

  5. Если у драйвера есть подпрограмма DpcForIsr , вызовите IoRequestDpc с указателями на текущий IRP, целевой объект устройства и сохраненный контекст. IoRequestDpc помещает подпрограмму DpcForIsr в очередь, когда IRQL опускается ниже DISPATCH_LEVEL на процессоре.

    Если у драйвера есть подпрограмма CustomDpc , вызовите KeInsertQueueDpc с указателем на объект DPC (связанный с подпрограммой CustomDpc ) и указателем на любой сохраненный контекст, который потребуется подпрограмме CustomDpc для завершения операции. Как правило, ISR также передает указатели на текущий IRP и целевой объект устройства. Подпрограмма CustomDpc запускается, как только IRQL опускается ниже DISPATCH_LEVEL на процессоре.

  6. Верните значение TRUE , чтобы указать, что устройство создало прерывание.

Как правило, ISR не выполняет фактическую обработку ввода-вывода для удовлетворения IRP. Вместо этого он останавливает прерывание устройства, настраивает необходимые сведения о состоянии и помещает в очередь DpcForIsr или CustomDpc драйвера, чтобы выполнить обработку ввода-вывода, необходимую для удовлетворения текущего запроса, вызвавшего прерывание устройства.

IsR должен выполняться в DIRQL в течение кратчайшего интервала. В соответствии с этим руководством увеличивается пропускная способность ввода-вывода для каждого устройства на компьютере, так как выполнение в DIRQL маскирует все прерывания, которым система назначила меньшее или равное значение IRQL.

SynchronizeIrql объектов прерываний драйвера, указанный, когда драйвер с именем IoConnectInterrupt определяет DIRQL, в котором выполняется ISR драйвера. Дополнительные сведения см. в разделе Синхронизация доступа к данным устройства.