Файловая система скорее всего будет повторно использовать IRP, если полученный запрос можно преобразовать в единый запрос к устройству. Например, если приложение выдаст запрос на чтение первых 512 байтов из файла на дискете, файловая система FAT просто вызовет драйвер диска, попросив его считать один сектор с того места на дискете, где начинается нужный файл.
Для поддержки использования несколькими драйверами IRP содержит набор блоков стека (не путать со стеком потока). Эти блоки данных — по одному на каждый вызываемый драйвер — хранят информацию, необходимую каждому драйверу для обработки своей части запроса (например, номер функции, параметры, сведения о контексте драйвера). Как показано на рис. 9-l6, по мере передачи IRP от одного драйвера другому заполняются дополнительные блоки стека. IRP можно считать аналогом стека в отношении добавления и удаления данных. Ho IRP не сопоставляется ни с каким процессом, и его размер фиксирован. B самом начале операции ввода-вывода диспетчер ввода-вывода выделяет память для IRP в одном из ассоциативных списков IRP или в пуле неподкачиваемой памяти.
ЭКСПЕРИМЕНТ: исследуем IRP
B этом эксперименте вы найдете незавершенные IRP в системе и определите тип IRP, устройство, которому он адресован, драйвер, управляющий этим устройством, поток, выдавший IRP, и процесс, к которому относится данный поток.
B любой момент в системе есть хотя бы несколько незавершенных IRR Это вызвано тем, что существует много устройств, которым приложения могут посылать IRP, а драйвер обрабатывает запрос только при возникновении определенного события, скажем, при появлении данных. Один из примеров — чтение с сетевого устройства. Увидеть незавершенные IRP в системе позволяет команда !irpfind отладчика ядра:
Строка, выделенная в выводе, описывает IRP, адресованный драйверу Kbdclass, так что этот IRP скорее всего был выдан потоком необработанного ввода для подсистемы Windows, принимающим ввод с клавиатуры. Изучение IRP с помощью команды !irp показывает следующее:
Активный блок стека (помечаемый префиксом «›», находится в самом низу. Основной номер функции равен 3, что соответствует IRP_MJ_READ.
Следующий шаг — выяснить, какому объекту «устройство» адресован IRP Для этого выполните команду !devobj, указав адрес объекта «устройство», взятый из активного блока стека:
Устройство, которому адресован данный IRP, — KeyboardClassl. Наличие объекта «устройство», принадлежащего драйверу Termdd, сообщает, что этот объект представляет ввод от клиента службы терминалов, а не с физической клавиатуры. (Листинг был получен в системе с Windows XP.)
Детальные сведения о потоке и процессе, выдавшем этот IRP, можно просмотреть командами !thread и /process:
Найдя этот поток в Process Explorer ( www.sysinternals.com) на вкладке Threads окна свойств для Csrss.exe, вы убедитесь, что, судя по именам функций в его стеке, он действительно является потоком необработанного ввода (raw input thread) для подсистемы Windows.
После того как драйвер диска завершает передачу данных, диск генерирует прерывание, и ввод-вывод завершается (рис. 9-17).
Рис. 9-17. Завершение обработки запроса на ввод-вывод к многоуровневым драйверам
B качестве альтернативы повторному использованию единственного IRP файловая система может создать группу сопоставленных IRP (associated IRPs), которые будут обрабатываться параллельно. Например, если данные, которые нужно считать из файла, разбросаны по всему диску, драйвер файловой системы может создать несколько IRP, каждый из которых инициирует чтение данных из отдельного сектора. Этот случай иллюстрирует рис. 9-18.
Читать дальше
Конец ознакомительного отрывка
Купить книгу