Внутри одной процедуры отправки у нас есть следующий код:
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
может быть ЛОЖЬ, и в этом случае получение спин-блокировки кажется очень тяжелым.
Мне не очень знакома многопоточность, особенно в режиме ядра. Я знаю, что это глупый вопрос, но я заблудился. Каково было бы правильное решение в этом случае? Спасибо.
этот флаг указывает, что устройство должно быть удалено, поэтому оно работает в одну сторону
для этого особого существует Защита от падения
вам нужно иметь 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_LEVELIoReleaseRemoveLockAndWait
должен быть вызван в PASSIVE_LEVEL
Других решений пока нет …