Драйвер Windows, получение спин-блокировки и проверка состояния

Внутри одной процедуры отправки у нас есть следующий код:

if (DeviceExtension->Flag)
{
KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceExtension->SpinLock, &LockHandle);

//... when we will enter here, DeviceExtension->Flag can already be set to FALSE.

KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);
}

Внутри другой процедуры отправки у нас есть следующий код:

KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceExtension->SpinLock, &LockHandle);

//...

DeviceExtension->Flag = FALSE;
KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);

Поэтому, когда мы получим спин блокировку внутри первой процедуры отправки, DeviceExtension->Flag уже может быть установлен на FALSE по второй программе. Решением было бы получить спин-блокировку и затем проверить DeviceExtension->Flag, тем не мение DeviceExtension->Flag может быть ЛОЖЬ, и в этом случае получение спин-блокировки кажется очень тяжелым.

Мне не очень знакома многопоточность, особенно в режиме ядра. Я знаю, что это глупый вопрос, но я заблудился. Каково было бы правильное решение в этом случае? Спасибо.

0

Решение

этот флаг указывает, что устройство должно быть удалено, поэтому оно работает в одну сторону

для этого особого существует Защита от падения

вам нужно иметь EX_RUNDOWN_REF RunRef; член в расширении устройства вместо bool Flag

инициализировать его

ExInitializeRundownProtection(&RunRef);

когда вам нужно сделать какую-то операцию, только если устройство еще не удалено, вам нужно сделать:

if (ExAcquireRundownProtection(&DeviceExtension->RunRef))
{
// do something
ExReleaseRundownProtection(&DeviceExtension->RunRef)
}

И в IRP_MN_REMOVE_DEVICE обработчик вам нужно позвонить

ExWaitForRundownProtectionRelease(&DeviceExtension->RunRef);

и важное примечание — несмотря на то, что в MSDN заявил, что ExAcquireRundownProtection а также ExReleaseRundownProtection должен быть вызван на IRQL <= APC_LEVEL это ложь и ошибка. ExAcquireRundownProtection просто сделайте несколько взаимосвязанных операций с памятью, до какой точки RunRef — так что если это в пейджинге невыгружаемого пула — мы можем вызвать эту процедуру в любой IRQL, Расширение устройства находится в невыгружаемом пуле. ExReleaseRundownProtection можно дополнительно позвонить KeSetEvent с Подождите установлен в FALSE, в результате он может быть запущен на IRQL <= DISPATCH_LEVEL, ExReleaseRundownProtection мы типичный звонок из IoCompletion рутина (которая выполняется в IRQL это меньше или равно DISPATCH_LEVEL) вот тут все ок.

ExWaitForRundownProtectionRelease конечно должен быть вызван в <= APC_LEVEL потому что здесь мы можем подождать, но менеджер PnP отправляет IRP_MN_REMOVE_DEVICE в IRQL PASSIVE_LEVEL — так что опять все хорошо здесь


конечно ваш здесь можно использовать и Удалить замки которые делают почти так же, как защита от подробного описания. просто защита от подробного описания — больше новых API, и намного лучше разработанный / реализованный сравните удалить блокировки. Однако в документации для IoReleaseRemoveLock а также IoReleaseRemoveLock правильно заявил, что IRQL
<= DISPATCH_LEVEL
должно быть и IoReleaseRemoveLockAndWait должен быть вызван в PASSIVE_LEVEL

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]