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


Доступ к общим сведениям о состоянии

Используйте следующие общие рекомендации по проектированию и написанию подпрограмм SynchCritSection , поддерживающих состояние.

  • Для доступа к данным, к которым также обращается ISR, подпрограмма драйвера должна вызвать подпрограмму SynchCritSection . Код некритических разделов может быть прерван. Помните, что недостаточно просто получить спин-блокировку для защиты данных, к которым также обращается ISR, так как ISR выполняются в DIRQL, а получение спин-блокировки (KeAcquireSpinLock) приводит к тому, что IRQL только DISPATCH_LEVEL, что позволяет прерывать вызов ISR на текущем процессоре.

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

    Это предотвращает состязание и, возможно, состояние гонки между подпрограммами SynchCritSection (и ISR), пытающимися получить доступ к одному и тому же состоянию одновременно.

    Это также гарантирует, что каждая подпрограмма SynchCritSection возвращает управление как можно быстрее, так как одной подпрограмме SynchCritSection никогда не придется ждать, пока другая подпрограмма обновляет одни и те же сведения о состоянии для возврата управления.

  • Избегайте написания одной крупной подпрограммы SynchCritSection общего назначения, которая выполняет больше тестирования условий, чтобы определить, что делать, чем на самом деле делать полезную работу. С другой стороны, избегайте использования множества подпрограмм SynchCritSection , которые никогда не выполняют условную инструкцию, так как каждая из них обновляет только один байт сведений о состоянии.

  • Каждая подпрограмма SynchCritSection должна возвращать управление как можно быстрее, так как выполнение любой подпрограммы SynchCritSection предотвращает выполнение ISR драйвера.

Ниже приведен способ поддержания счетчика таймера в расширении устройства. Предположим, что драйвер использует счетчик, чтобы определить, истекло ли время ожидания операции ввода-вывода. Также предположим, что драйвер не перекрывает операции ввода-вывода.

  • Подпрограмма StartIo драйвера инициализирует счетчик таймера каким-то начальным значением для каждого запроса ввода-вывода. Затем драйвер добавляет секунду к значению времени ожидания устройства, если его подпрограмма IoTimer только что вернула управление.

  • IsR драйвера должен установить для этого счетчика таймера значение минус один.

  • Подпрограмма IoTimer драйвера вызывается один раз в секунду для считывания счетчика времени и определения того, задано ли в ISR значение минус один. В противном случае подпрограмма IoTimer уменьшает счетчик с помощью KeSynchronizeExecution для вызова подпрограммы SynchCritSection_1.

    Если счетчик переходит к нулю, указывая, что время ожидания запроса истекло, SynchCritSection_1 подпрограмма вызывает SynchCritSection_2 подпрограмму для программирования операции сброса устройства. Если значение счетчика равно минус 1, то подпрограмма IoTimer просто возвращает значение.

  • Если подпрограмма DpcForIsr драйвера должна перепрограммировать устройство, чтобы начать операцию частичной передачи, она должна повторно инициализировать счетчик таймера, как это сделала подпрограмма StartIo .

    Подпрограмма DpcForIsr также должна использовать KeSynchronizeExecution для вызова SynchCritSection_2 подпрограммы или, возможно, подпрограммы SynchCritSection_3, чтобы запрограммировать устройство для другой операции передачи.

В этом сценарии драйвер имеет несколько подпрограмм SynchCritSection , каждая из которых имеет дискретные, определенные обязанности; один для поддержания счетчика таймера, а другой — для программирования устройства. Каждая подпрограмма SynchCritSection может быстро возвращать управление, так как она выполняет одну дискретную задачу.

Обратите внимание, что драйвер имеет одну подпрограмму SynchCritSection_1, которая вместе с ISR драйвера поддерживает состояние счетчика таймера. Таким образом, между несколькими подпрограммами SynchCritSection и ISR нет состязаний за доступ к счетчику таймера.