Прежде чем перейти к моему вопросу, я перейду к тому, с чем я сейчас работаю, чтобы у вас было хорошее представление о том, что я уже сделал / попробовал.
У меня есть многопоточное пользовательское приложение для рабочего стола Windows, которое выполняет вызовы DeviceIOControl для драйвера KMDF (чисто программный, без аппаратного обеспечения). Существует 5 отдельных потоков, которые постоянно выполняют один и тот же пользовательский вызов IOCTL для драйвера. Этот запрос состоит из:
Драйвер в настоящее время делает это последовательно, и основное узкое место в моем приложении пользовательского режима ожидает завершения чтения памяти, и все должно быть завершено, прежде чем сцена может быть «визуализирована».
Я максимально сократил количество запросов DeviceIOControl, поэтому теперь я изучал перекрывающийся ввод-вывод и позволял каждому потоку отправлять запросы асинхронно. У меня вопрос, стоит ли даже пытаться что-то предпринять, поскольку я не знаю, могу ли я использовать несколько потоков в моем драйвере для одновременного чтения с разных адресов.
ОК, похоже, самая важная часть вашего вопроса здесь:
Я искал повсюду, пытаясь выяснить, что именно открытие файла с перекрытием действительно меняет отношение к тому, как WDF обрабатывает запросы IOCTL […]
Это ничего не меняет; все запросы к драйверам устройств являются асинхронными.
Когда вы выполняете ввод-вывод на синхронном дескрипторе, Windows выдает драйвер асинхронного ввода-вывода от вашего имени и ожидает его завершения. Насколько я знаю, драйвер даже не может определить, был ли исходный запрос синхронным или перекрытым. [Редактировать: это не совсем так. Как указывает RbMm в комментариях, ядро фактически проводит различие между синхронным и асинхронным вводом / выводом, но с практической точки зрения это не должно иметь значения для вас.]
В любом случае, если драйвер в данный момент работает только в одном потоке, использование перекрывающегося ввода-вывода не поможет. Вам придется изменить драйвер. И наоборот, модификации драйвера должно быть достаточно; вам, вероятно, не нужно менять приложение. (Исключение: я не уверен, является ли законным использование одного и того же синхронного дескриптора одновременно из нескольких потоков, поэтому я рекомендую каждому потоку открывать свой дескриптор для устройства, по крайней мере, пока вы не убедитесь, что драйвер работает по желанию.)
Я не знаком с WDF, но запись MSDN Методы диспетчеризации для запросов ввода / вывода выглядит актуально.
На первых порах очень важно, как пользовательский режим открывает файл — в синхронном или асинхронном режиме? (FILE_FLAG_OVERLAPPED
за CreateFile
или же FILE_SYNCHRONOUS_IO_[NO]NALERT
за ZwOpenFile
или же ZwCreateFile
)
если файл открыт в синхронном режиме (FO_SYNCHRONOUS_IO
будет в FILE_OBJECT.Flags
Подсистема ввода / вывода сериализует все запросы в файл — поэтому она не отправляет новый запрос на ваше устройство, пока предыдущий не будет завершен. с асинхронным файловым объектом — такого ограничения нет — запрос (IRP) будет просто отправлен на ваше устройство
если ты так говоришь
Однако сами потоки не зависят друг от друга.
вам нужно открыть файл как асинхронный (с FILE_FLAG_OVERLAPPED
) если потоки имеют общий дескриптор файла (FILE_OBJECT
) или каждый поток должен отдельно открыть собственный личный файл на вашем устройстве. думаю лучше поделится асинхронным файлом.
со стороны водителя вы должны использовать WdfIoQueueDispatchParallel
тип отправки очереди. так что просто возьмите запрос (IRP) обработайте его и завершите (насколько я понимаю, вы не отправляете этот запрос другому драйверу или не помещаете в какую-то другую очередь)
По сути, я спрашиваю, с перекрытием ввода-вывода, это
эквивалент одного экземпляра моего драйвера, обрабатывающего каждый поток, или это
еще один драйвер получает кучу запросов из 5 потоков и
изо всех сил, чтобы не отставать?
у тебя всегда есть один экземпляр драйвера и количество устройств точно, сколько вы его создаете. если вы создадите только одно устройство — и будет только это один устройство. все файлы будут открыты на этом устройстве. все запросы (от любого процесса / потока) будут отправлены на этот единственный экземпляр устройства.
если вы используете так же файл для всех потоков, и это будет синхронный файл — подсистема ввода-вывода сериализует все запросы к драйверу — и это плохо для вас. клиенты вашего драйвера (устройства) должны открывать файл как асинхронный (или каждый клиент открывает свой личный файл). со стороны водителя — нужно WdfIoQueueDispatchParallel
Тип отправки очереди, потому что, как я понимаю, все запросы независимы, и вам не нужна синхронизация между запросами.