Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Новые драйверы должны использовать платформу очередей IRP с безопасной отменой вместо методов, описанных в этом разделе.
Как и драйвер контроллера floppy системы, драйвер с выделенным потоком для устройства, а не подпрограмма StartIo, обычно управляет собственной очередью IRP в двухсвязной взаимоблокируемой очереди. Поток драйвера извлекает IRP из своей взаимоблокированной очереди, когда на устройстве выполняется работа.
В общем, драйвер должен управлять синхронизацией потока с любыми ресурсами, общими для потока и других процедур драйвера. Драйвер также должен иметь какой-то способ уведомить свой поток, созданный драйвером, о том, что IRP ставятся в очередь. Как правило, поток ожидает объект диспетчера, который хранится в расширении устройства, пока диспетчерские подпрограммы драйвера не установят объект диспетчера в состояние Signaled после вставки IRP в защищённую очередь.
При вызове подпрограмм диспетчеризации драйвера каждая из них проверяет параметры в стеке ввода-вывода IRP запроса и, если параметры допустимы, ставит запрос в очередь для дальнейшей обработки. Для каждой IRP, поставленной в очередь потоков, выделенных драйвером, подпрограмма диспетчера должна настроить контекст, необходимый для обработки этой IRP, прежде чем она вызовет ExInterlockedInsertXxxList. Расположение стека ввода-вывода драйвера в каждом IRP позволяет потоку драйвера получить доступ к расширению устройства целевого объекта устройства, где драйвер может разделять сведения о контексте с потоком, когда поток удаляет каждый IRP из очереди.
Драйвер, обрабатывающий отменяемые IRP в очереди, должен реализовать процедуру Cancel. Так как IRP отменяются асинхронно, необходимо убедиться, что ваш драйвер избегает состояния гонки, которые могут привести к проблемам. Дополнительные сведения об условиях гонки, связанных с отменой IRP, и методах их предотвращения см. в разделе "Синхронизация отмены IRP".
Любой поток, созданный драйвером, выполняется в IRQL = PASSIVE_LEVEL и в базовом приоритете времени выполнения, заданном ранее, когда драйвер вызвал PsCreateSystemThread. Вызов потоком функции ExInterlockedRemoveHeadList временно повышает IRQL до DISPATCH_LEVEL на текущем процессоре, когда IRP удаляется из внутренней очереди драйвера. Исходный IRQL восстанавливается до PASSIVE_LEVEL при возврате из этого вызова.
Любой поток драйвера (или обратный вызов рабочего потока, предоставленный драйвером) должен тщательно управлять irQLs, с которыми он выполняется. Например, рассмотрим следующее:
Поскольку системные потоки обычно выполняются на уровне IRQL = PASSIVE_LEVEL, поток драйвера может ожидать, пока объекты диспетчера, определенные ядром, перейдут в сигнальное состояние.
Например, выделенный устройством поток может ожидать, пока другие драйверы удовлетворяют событию и завершают некоторое количество частичных операций irps, которые поток настраивает с помощью IoBuildSynchronousFsdRequest.
Однако такой выделенный устройством поток должен вызывать IRQL на текущем процессоре, прежде чем вызывать определенные подпрограммы поддержки.
Например, если драйвер использует DMA, его выделенный для устройства поток должен вложить свои вызовы в AllocateAdapterChannel и FreeAdapterChannel между вызовами KeRaiseIrql и KeLowerIrql , так как эти подпрограммы и некоторые другие подпрограммы поддержки для операций DMA должны вызываться в IRQL = DISPATCH_LEVEL.
Помните, что подпрограммы StartIo выполняются в DISPATCH_LEVEL, поэтому драйверы, использующие DMA, не должны вызывать подпрограммы KeXxxIrql из своих подпрограмм StartIo .
Созданный драйвером поток может получить доступ к страницируемой памяти, так как он выполняется в контексте непарбитарных потоков (собственный) в IRQL = PASSIVE_LEVEL, но многие другие стандартные подпрограммы драйверов выполняются в IRQL >= DISPATCH_LEVEL. Если созданный драйвером поток выделяет память, доступ к которому можно получить с помощью такой подпрограммы, он должен выделить память из непагрегированного пула. Например, если выделенный устройством поток выделяет любой буфер, к которому позже будет обращаться ISR драйвера или SynchCritSection, AdapterControl, AdapterListControl, ControllerControl, DpcForIsr, CustomDpc, IoTimer, CustomTimerDpc, или, в драйвере более высокого уровня, подпрограмме IoCompletion, память, выделенная потоком, не может быть страничной.
Если драйвер хранит общие сведения о состоянии или ресурсы в расширении устройства, поток драйвера (например, подпрограмма StartIo ) должен синхронизировать доступ к физическому устройству и общим данным с другими подпрограммами драйвера, которые обращаются к тому же устройству, расположению памяти или ресурсам.
Если поток разделяет устройство или состояние с ISR, он должен использовать KeSynchronizeExecution для вызова подпрограммы SynchCritSection, предоставленную драйвером, чтобы программировать устройство или получить доступ к общему состоянию. См. раздел "Использование критически важных разделов".
Если поток разделяет состояние или ресурсы с подпрограммами, отличными от ISR, драйвер должен защитить общее состояние или ресурсы с помощью драйвер-инициализированной спин-блокировки, для которой драйвер предоставляет хранилище. Дополнительные сведения см. в разделе "Замки спина".
Дополнительные сведения о компромиссах в проектировании при использовании потока драйвера для медленного устройства см. в разделе "Опрос устройства". См. также управление приоритетами оборудования. Дополнительные сведения о irQLs для конкретных подпрограмм поддержки см. на странице справки по подпрограмме.