Вы можете получить список всех функций, определенных драйвером для своих процедур диспетчеризации. Для этого введите команду !drvobj отладчика ядра и после имени (или адреса) объекта «драйвер» укажите значение 7. Следующий вывод показывает, что драйверы поддерживают 28 типов IRR
Каждый IRP, пока он активен, хранится в списке IRP, сопоставленном с потоком, который выдал запрос на ввод-вывод. Это позволяет подсистеме ввода-вывода найти и отменить любые незавершенные IRP, если выдавший их поток завершается.
ЭКСПЕРИМЕНТ: просмотр незавершенных IRP потока
Команда !thread выводит любые IRP, сопоставленные с потоком. Запустите отладчик ядра в работающей системе и найдите процесс диспетчера управления сервисами (Services.exe) в выводе, сгенерированном командой !process\
Теперь создайте дамп потоков для процесса, выполнив команду !process применительно к объекту «процесс». Вы должны увидеть множество потоков, у большинства из которых есть IRP; эти IRP отображаются в блоке IRP List информации о потоке (заметьте, что отладчик выводит лишь первые 17 IRP для потока, у которого имеется более 17 незавершенных запросов ввода-вывода):
У этого IRP основной номер функции — 3, что соответствует IRP_ MJ_READ. Он содержит один блок стека и адресован устройству, принадлежащему драйверу Npfs (Named Pipe File System). (Информацию о Npfs см. в главе 13.)
Управление буфером IRP
Когда приложение или драйвер устройства неявно создает IRP с помощью системного сервиса NtReadFile, NtWriteFile или NtDeviceIoControlFile (этим сервисам соответствуют Windows-функции ReadFile, WriteFile и DeviceIoControt), диспетчер ввода-вывода определяет, должен ли он участвовать в управлении буферами ввода и вывода вызывающего потока. Диспетчер ввода-вывода поддерживает три вида управления буферами.
• Буферизованный ввод-вывод (buffered I/O)Диспетчер ввода-вывода выделяет в пуле неподкачиваемой памяти буфер, равный по размеру буферу вызывающего потока. Создавая IRP при операциях записи, диспетчер ввода-вывода копирует данные из буфера вызывающего потока в выделенный буфер. Завершая обработку IRP при операциях чтения, диспетчер ввода-вывода копирует данные из выделенного буфера в пользовательский буфер и освобождает выделенный буфер.
• Прямой ввод-вывод (direct I/O)Создавая IRP, диспетчер ввода-вывода блокирует пользовательский буфер в памяти (делает его неподкачиваемым). Закончив работу с IRP, диспетчер ввода-вывода разблокирует буфер. Диспетчер хранит описание этой памяти в форме MDL (memory descriptor list). MDL указывает объем физической памяти, занятой буфером (подробнее о MDL см. Windows DDK). Устройствам, использующим DMA (прямой доступ к памяти), требуется лишь физическое описание буфера, поэтому таким устройствам достаточно MDL. (Устройства, поддерживающие DMA, передают данные в память компьютера напрямую, не используя процессор.) Ho, если драйверу нужен доступ к содержимому буфера, он может спроецировать его на системное адресное пространство.
• Ввод-вывод без управления (neither I/O)Диспетчер ввода-вывода не участвует в управлении буферами. Ответственность за управление ими возлагается на драйвер устройства.
При любом типе управления буферами диспетчер ввода-вывода помещает в IRP ссылки на буферы ввода и вывода. Тип управления буферами, реализуемого диспетчером ввода-вывода, зависит от типа управления, запрошенного драйвером для операций конкретного типа. Драйвер регистрирует нужный ему тип управления буферами для операций чтения и записи в объекте «устройство», который представляет устройство. Операции управления вводом-выводом на устройстве (выполняемые NtDeviceIoControlFile) задаются определенными в драйвере управляющими кодами ввода-вывода. Управляющий код включает тип управления буферами со стороны диспетчера ввода-вывода при обработке IRP с данным кодом.
Читать дальше
Конец ознакомительного отрывка
Купить книгу