Удаление устройства WDM в драйвере PnP

У меня есть вопрос об удалении устройства.

Когда мы хотим уведомить PnP-менеджера о том, что устройство исчезло, мы звоним IoInvalidateDeviceRelations с BusRelations, После этого ОС отправит IRP_MN_QUERY_DEVICE_RELATIONS запрос с BusRelations, В этом обработчике запросов мы исключим устройство из массива и сделаем еще одну необходимую работу, чтобы "отключить" его от шины, также мы установим RemovePending флаг в своем расширении устройства.

Я не понимаю, как обрабатывать входящие запросы ввода-вывода на устройство после того, как оно становится "удалить в ожидании" и до отправки ОС IRP_MN_REMOVE_DEVICE запрос. Должны ли мы проверить RemovePending флаг и возврат STATUS_DEVICE_DOES_NOT_EXIST или мы должны действовать как обычно?

Теперь представьте, что IRP_MN_REMOVE_DEVICE запрос наконец-то прибыл. MSDN говорит, что мы должны позвонить IoReleaseRemoveLockAndWait это освобождает текущее приобретение удаления блокировки, предотвращает последующие приобретения и ожидает, пока существующие приобретения будут освобождены. Так что это заставляет нас всегда получать блокировку удаления внутри обработчика запросов PnP с IoAcquireRemoveLock; и выпустить его с IoReleaseRemoveLockAndWait за IRP_MN_REMOVE_DEVICE или с IoReleaseRemoveLock для других второстепенных кодов.

Я не понимаю, почему нам нужно получить блокировку удаления внутри обработчика запросов PnP? В моем понимании нам нужно получить блокировку удаления только для ожидающего IRP и освободить его, когда такой IRP завершен. Таким образом, пользователи Windows могут предоставить нам IoWaitForExistingRemoveLocks рутина вместо IoReleaseRemoveLockAndWait,

Извините, если это немного грязно, я просто не могу понять это. Благодарю.

1 ответ

Решение

После этого ОС отправит IRP_MN_QUERY_DEVICE_RELATIONS запрос с BusRelations, В этом обработчике запросов мы исключим устройство из массива и сделаем еще одну необходимую работу, чтобы "отключить" его от шины, также мы установим RemovePending флаг в своем расширении устройства.

здесь нужно только исключить устройство из массива и установить RemovePending флаг в своем расширении устройства. но сделать другую необходимую работу, чтобы "отключить" его от шины - нужно делать только при обработке IRP_MN_REMOVE_DEVICE (после того, как устройство не было включено в самый последний ответ водителя автобуса на IRP_MN_QUERY_DEVICE_RELATIONS запрос BusRelations - или другими словами - когда RemovePending пометить в своем устройстве расширение)

как обрабатывать входящие запросы ввода-вывода к устройству после того, как оно станет "удалить в ожидании" и перед отправкой ОС IRP_MN_REMOVE_DEVICE запрос. Должны ли мы проверить RemovePending флаг и возврат STATUS_DEVICE_DOES_NOT_EXIST или мы должны действовать как обычно?

Я думаю, что возможно оба поведения - вы можете обработать его как обычно и можете вернуться STATUS_DEVICE_DOES_NOT_EXIST тоже. и предположим следующую ситуацию - вы получите некоторый запрос ввода-вывода одновременно с процессом удаления устройства. когда вы проверяете RemovePending флаг - это еще не установлен. и вы начинаете обрабатывать запрос "как обычно". но сразу после проверки RemovePending флаг внутри запроса ввода-вывода, вы можете установить его во время обработки IRP_MN_QUERY_DEVICE_RELATIONS запрос с BusRelations, и эта ситуация имеет прямое отношение к смыслу, используя удаление блокировок или защиту от потери мощности.

мы действительно можем использовать защиту от пониженной нагрузки вместо удаления блокировок почти таким же образом и точно в тех же местах и ​​по той же причине, что и удаление блокировок. и я думаю, что API защиты от понижения (больше нового сравнить удалить замки) - лучший дизайн и лучше для использования (однако отличается минимально)

Я не понимаю, почему нам нужно получить блокировку удаления внутри обработчика запросов PnP?

Прежде всего, обратите внимание, что об удалении блокировки сказано только в разделе "Удаление устройства из функционального драйвера". Вы, насколько я понимаю, не работаете, но водитель автобуса - так что Удаление устройства в драйвере автобуса больше подходит для вас. и в документации по удалению устройства в драйвере функции существует серьезная ошибка - совет сначала позвоните IoReleaseRemoveLockAndWait в точке 4 - до точки 8 - Пройдите IRP_MN_REMOVE_DEVICE запрос до следующего водителя. но правильно должно быть

Водитель должен позвонить IoReleaseRemoveLockAndWait после того, как он проходит IRP_MN_REMOVE_DEVICE запрос к следующему более низкому драйверу, и прежде чем он освободит память, вызывает IoDetachDevice или звонки IoDeleteDevice,

это правильно и указано в разделах " Использование удаленных блокировок" и " IoReleaseRemoveLockAndWait". забавно что в старых версиях msdn было

вызов IoReleaseRemoveLockAndWait прежде чем это пройдет..

но теперь это исправлено. почему после? потому что следующий более низкий драйвер может ожидать некоторых IRP (на которых мы называем IoAcquireRemoveLock или же ExAcquireRundownProtection) и завершить его только когда получил IRP_MN_REMOVE_DEVICE и наш водитель звонит IoReleaseRemoveLock или же ExReleaseRundownProtection только когда этот IRP будет завершен. как результат, если вызов IoReleaseRemoveLockAndWait или же ExWaitForRundownProtectionRelease перед передачей удаления IRP следующему более низкому драйверу - мы можем ждать здесь вечно - следующий более низкий драйвер не может завершить некоторый IRP (пока не получен запрос на удаление), и мы не снимаем защиту от удаления блокировки или восстановления.

так для чего нам нужно снять замки или защиту от изношенности? потому что мы можем получить IRP_MN_REMOVE_DEVICE одновременно с другими запросами ввода-вывода. и эти запросы ввода-вывода могут использовать некоторые ресурсы на устройстве. от другого размера, когда мы обрабатываем IRP_MN_REMOVE_DEVICE мы уничтожаем эти ресурсы. что будет, если мы будем использовать какой-то ресурс в запросе ввода-вывода после того, как он будет уничтожен в IRP_MN_REMOVE_DEVICE? думаю не нужно отвечать. Для предотвращения этого и существуют снятия замков или защиты от изношенности. перед использованием любого ресурса (который будет уничтожен при удалении) нужно вызвать IoAcquireRemoveLock или же ExAcquireRundownProtection и используйте его, только если возвращен статус ok. после того как мы закончим использовать ресурсный вызов IoReleaseRemoveLock или же ExReleaseRundownProtection, И в IRP_MN_REMOVE_DEVICE мы называем IoReleaseRemoveLockAndWait или же ExWaitForRundownProtectionRelease, после того, как этот вызов возвращен - мы можем быть уверены, что никто не использует наши ресурсы и никогда не будет использоваться больше (звонки IoAcquireRemoveLock или же ExAcquireRundownProtection вернуть статус ошибки (false)). в этот момент мы можем безопасно начать уничтожать ресурсы: освобождает память (и т. д.), вызывает IoDetachDevice, IoDeleteDevice,

указатель на следующее-нижнее устройство - это тоже ресурс, который мы используем в процессе IO-запроса и уничтожаем в IRP_MN_REMOVE_DEVICE (по телефону IoDetachDevice). действительно верны вызов IofCallDriver(_nextDeviceObject, Irp); (пока обрабатываете какой-нибудь IO-запрос) после вызова IoDetachDevice(_nextDeviceObject); (внутри IRP_MN_REMOVE_DEVICE) потому что это удаление блокирует (или я использую саму защиту здесь) всегда используется в функциях и драйверах фильтров. для драйвера шины, где у нас обычно нет указателя на следующее-нижнее устройство (PDO не подключен к другому устройству, когда FDO подключен к PDO и фильтр всегда подключен к чему-либо) - может не потребоваться блокировка (или вообще защита от выбрасывания). это зависит - существуют ли другие ресурсы - использованные и уничтоженные (при удалении).

а для автобусных устройств - обычная ситуация, когда мы попали IRP_MN_REMOVE_DEVICE 2 раза - сначала, прежде чем устройство помечено как RemovePending - так мы переходим к пункту 4. и после устройства, отмеченного как RemovePending (таким образом, устройство не было включено в последний ответ драйвера шины на запрос IRP_MN_QUERY_DEVICE_RELATIONS для BusRelations), мы наконец уничтожаем ресурсы и вызываем IoDeleteDevice

Другие вопросы по тегам