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


Использование блокировок фреймворка

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

Блокировки синхронизации обратных вызовов

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

Эти блокировки синхронизации обратного вызова, связанные с объектами устройств фреймворка и объектами очереди, также могут быть приобретены драйверами. Чтобы получить блокировку синхронизации, драйвер вызывает WdfObjectAcquireLock. Чтобы освободить блокировку, драйвер вызывает WdfObjectReleaseLock.

Вам может понадобиться, чтобы ваш драйвер использовал блокировки для синхронизации обратного вызова, если драйвер использует синхронизацию на уровне устройства или уровня очереди для функций обратного вызова, связанных с обработкой запросов ввода-вывода, но при этом необходимо синхронизировать код, выполняемый на уровне IRQL = PASSIVE_LEVEL, с функциями обратного вызова, работающими на уровне IRQL = DISPATCH_LEVEL. Это связано с тем, что драйверы могут использовать автоматическую синхронизацию только для функций обратного вызова, которые выполняются в том же IRQL.

Например, драйвер может автоматически синхронизировать объект рабочего элемента, только если уровень выполнения родительского объекта - WdfExecutionLevelPassive (так как функция обратного вызова рабочего элемента всегда выполняется на уровне IRQL= PASSIVE_LEVEL). Поэтому, если драйвер указывает WdfExecutionLevelDispatch в элементе ExecutionLevel структуры WDF_OBJECT_ATTRIBUTES объекта устройства, драйвер не может задать элемент AutomaticSerialization в структуре конфигурации дочернего рабочего элемента. Вместо этого драйвер должен получить блокировку для синхронизации функций обратных вызовов EvtWorkItem с функциями обратных вызовов родительского объекта устройства.

Блокировки ожидания фреймворка

Используйте блокировки ожидания платформы для синхронизации доступа к данным драйвера из кода, который выполняется в IRQL = PASSIVE_LEVEL. Прежде чем драйвер сможет использовать блокировку ожидания в рамках платформы, он должен вызвать WdfWaitLockCreate для создания объекта блокировки ожидания. Затем драйвер может вызвать WdfWaitLockAcquire, чтобы получить блокировку и WdfWaitLockRelease, чтобы освободить её.

Крутящие блокировки в рамках платформы

Используйте спин-блокировки фреймворка для синхронизации доступа к данным драйвера из кода, работающего на уровне IRQL <= DISPATCH_LEVEL. Когда поток драйвера получает спин-блокировку, система устанавливает IRQL потока на DISPATCH_LEVEL. Когда поток освобождает блокировку, система восстанавливает IRQL потока до предыдущего уровня.

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

Прежде чем драйвер сможет использовать спин-блокировку фреймворка, необходимо вызвать WdfSpinLockCreate для создания объекта спин-блокировки. Затем драйвер может вызвать WdfSpinLockAcquire, чтобы получить блокировку и WdfSpinLockRelease, чтобы освободить ее.

Пример использования spin-блокировок см. в разделе Синхронизация отмены отправленных запросов.

Блокировки прерываний фреймворка

Для объектов прерываний, поддерживающих обработку прерываний DIRQL, блокировки прерываний являются спинлоками. После того как драйвер получает блокировку прерывания, он работает на DIRQL устройства, пока не освободит блокировку. Дополнительные сведения об использовании блокировок прерываний см. в разделе "Синхронизация кода прерываний".

Для объектов прерываний, поддерживающих обработку на пассивном уровне, блокировки прерываний являются блокировками ожидания. После получения блокировки ожидания прерывания драйвер выполняется на уровне IRQL = PASSIVE_LEVEL, пока она не будет снята. Для получения дополнительной информации об обработке пассивного уровня см. поддержка прерываний пассивного уровня.