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


Написание ISR

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

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

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

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

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

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

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

  • В противном случае ISR, при необходимости, очищает прерывание, сохраняет нужный контекст устройства и добавляет DPC в очередь для завершения операции ввода-вывода на более низком уровне IRQL. Для получения дополнительной информации см. «Объекты DPC и DPCs». Затем 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 драйвера. Дополнительные сведения см. в разделе "Синхронизация доступа к данным устройства".