ВУЗ:
Составители:
45
− После вызова функции IoCompleteRequest диспетчер ввода-вывода
отменяет IRP и выдает заранее подготовленное драйвером событие.
− Программист драйвера должен обеспечить существование объекта
события на момент выдачи его диспетчером ввода-вывода.
Следует также следить за тем, чтобы функции вызывались только на
пользовательском уровне прерываний (PASSIVE_LEVEL).
Рассмотрим пример, который приведет
к состоянию блокировки.
PIRP Irp = IoBuildSynchronousFsdRequest(…);
ExAcquireFastMutex(…); // Захват мьютекса Здесь IRQL
// переключается на APC_LEVEL
NSTATUS status = IoCallDriver(…);
if (status == STATUS_PENDING)
KeWaitForSingleObject(…); // !!!
ExReleaseFastMutex(…); // Освобождение мьютекса
После завершения IRP функция IoCompleteRequest запланирует APC
(асинхронный вызов процедуры) для завершения начатого. APC, если бы она
смогла, выполниться, инициировала бы событие. Однако, выполниться она не
может, так как захват мьютекса уже перевел IRQL на APC_LEVEL, который не
может быть прерван процедурой того же уровня. В итоге, функция не может
быть
завершена (не сгенерировано событие), а мьютекс не может быть освобожден (так
как драйвер не может вернуть STATUS_PENDING).
Для того, чтобы избежать такой блокировки при синхронизации IRP,
отправляемых другому драйверу, можно поступить по разному.
− Можно использовать обычный мьютекс, вместо быстрого, который
оставляет IRQL на уровне PASSIVE_LEVEL. При этом могут
выполняться
APC режима ядра.
− Можно использовать функцию KeEnterCriticalRegion, которая
отключает обычные APC режима ядра, а затем использовать функцию
ExAcquireFastMutexUnsafe для захвата мьютекса. Эта функция ожидает
вызова при отключенной доставке обычных APC режима ядра.
− После вызова функции IoCompleteRequest диспетчер ввода-вывода отменяет IRP и выдает заранее подготовленное драйвером событие. − Программист драйвера должен обеспечить существование объекта события на момент выдачи его диспетчером ввода-вывода. Следует также следить за тем, чтобы функции вызывались только на пользовательском уровне прерываний (PASSIVE_LEVEL). Рассмотрим пример, который приведет к состоянию блокировки. PIRP Irp = IoBuildSynchronousFsdRequest(…); ExAcquireFastMutex(…); // Захват мьютекса Здесь IRQL // переключается на APC_LEVEL NSTATUS status = IoCallDriver(…); if (status == STATUS_PENDING) KeWaitForSingleObject(…); // !!! ExReleaseFastMutex(…); // Освобождение мьютекса После завершения IRP функция IoCompleteRequest запланирует APC (асинхронный вызов процедуры) для завершения начатого. APC, если бы она смогла, выполниться, инициировала бы событие. Однако, выполниться она не может, так как захват мьютекса уже перевел IRQL на APC_LEVEL, который не может быть прерван процедурой того же уровня. В итоге, функция не может быть завершена (не сгенерировано событие), а мьютекс не может быть освобожден (так как драйвер не может вернуть STATUS_PENDING). Для того, чтобы избежать такой блокировки при синхронизации IRP, отправляемых другому драйверу, можно поступить по разному. − Можно использовать обычный мьютекс, вместо быстрого, который оставляет IRQL на уровне PASSIVE_LEVEL. При этом могут выполняться APC режима ядра. − Можно использовать функцию KeEnterCriticalRegion, которая отключает обычные APC режима ядра, а затем использовать функцию ExAcquireFastMutexUnsafe для захвата мьютекса. Эта функция ожидает вызова при отключенной доставке обычных APC режима ядра. 45
Страницы
- « первая
- ‹ предыдущая
- …
- 43
- 44
- 45
- 46
- 47
- …
- следующая ›
- последняя »