Чтение онлайн

ЖАНРЫ

3.Внутреннее устройство Windows (гл. 8-11)
Шрифт:

• Одна или несколько процедур завершения ввода-вывода У драйвера могут быть процедуры завершения ввода-вывода, уведомляющие его об окончании обработки IRP драйвером более низкого уровня. Например, диспетчер ввода-вывода вызывает процедуру завершения ввода-вывода драйве-

pa файловой системы, когда драйвер устройства заканчивает передачу данных в файл или из него. Эта процедура уведомляет драйвер файловой системы об удачном или неудачном завершении операции или о ее отмене, а также позволяет драйверу файловой системы освободить ресурсы.

• Процедура отмены ввода-вывода Если операция ввода-вывода может быть отменена, драйвер определяет одну или более процедур отмены ввода-вывода. Получив IRP для запроса ввода-вывода, который

может быть отменен, драйвер связывает с IRP процедуру отмены. Если поток, выдавший запрос на ввод-вывод, завершается до окончания обработки запроса или отменяет операцию (например, вызовом Windows-функции CancelIo), диспетчер ввода-вывода выполняет процедуру отмены, связанную с IRP (если таковая есть). Процедура отмены отвечает за выполнение любых действий, необходимых для освобождения всех ресурсов, выделенных при обработке IRP, а также за завершение IRP со статусом отмены.

• Процедура выгрузки Эта процедура освобождает все системные ресурсы, задействованные драйвером, после чего диспетчер ввода-вывода может удалить их из памяти. При выполнении процедуры выгрузки обычно освобождаются ресурсы, выделенные процедурой инициализации. Драйвер может загружаться и выгружаться во время работы системы.

• Процедура уведомления о завершении работы системы Эта процедура позволяет драйверу проводить очистку при завершении работы системы.

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

ПРИМЕЧАНИЕ Большинство драйверов устройств написано на С. Применение языка ассемблера крайне не рекомендуется из-за его сложности и из-за того, что он затрудняет перенос драйвера между аппаратными архитектурами вроде x86, х64 и IА64.

Объекты «драйвер» и «устройство»

Когда поток открывает описатель объекта «файл» (этот процесс описывается в разделе «Обработка ввода-вывода» далее в этой главе), диспетчер ввода-вывода, исходя из имени этого объекта, должен определить, к какому драйверу (или драйверам) нужно обратиться для обработки запроса. Более того, диспетчер ввода-вывода должен знать, где найти эту информацию, когда в следующий раз поток вновь воспользуется тем же описателем файла. Для этого предназначены следующие объекты.

Объект «драйвер», представляющий отдельный драйвер в системе. Именно от этого объекта диспетчер ввода-вывода получает адрес процедуры диспетчеризации (точки входа) драйвера.

Объект «устройство», представляющий физическое или логическое устройство в системе и описывающий его характеристики, например границы выравнивания буферов и адреса очередей для приема IRP, поступающих на это устройство.

Диспетчер ввода-вывода создает объект «драйвер» при загрузке в систему соответствующего драйвера и вызывает его инициализирующую процедуру (например, DriverEntry), которая записывает в атрибуты объекта точки входа этого драйвера.

После загрузки драйвер может создавать объекты «устройство» для представления устройств или даже для формирования интерфейса драйвера (вызовом IoCreateDevice или IoCreateDeviceSecure). Однако большинство PnP-драйверов создают объекты «устройство» с помощью своих процедур добавления устройств, когда диспетчер PnP информирует их о присутствии управляемого ими устройства. C другой стороны, драйверы, не отвечающие спецификации Plug and Play, создают объекты «устройство» при вызове диспетчером ввода-вывода их инициализирующих процедур. Диспетчер ввода-вывода выгружает драйвер после удаления

его последнего объекта «устройство», когда ссылок на устройство больше нет.

Создавая объект «устройство», драйвер может присвоить ему имя. Тогда этот объект помещается в пространство имен диспетчера объектов. Драйвер может определить имя этого объекта явно или позволить диспетчеру ввода-вывода сгенерировать его автоматически (о пространстве имен диспетчера объектов см. главу 3). По соглашению объекты «устройство» помещаются в каталог \Device пространства имен, недоступный приложениям через Windows API.

ПРИМЕЧАНИЕ Некоторые драйверы размещают объекты «устройство» в каталогах, отличных от \Device. Так, диспетчер томов Logical Disk Manager создает объекты «устройство», представляющие разделы жесткого диска, в каталоге \Device\HarddiskDmVolumes (подробнее на эту тему см. главу 10).

Чтобы сделать объект «устройство» доступным для приложений, драйвер должен создать в каталоге \Global?? (или в каталоге \?? в Windows 2000) символьную ссылку на имя этого объекта в каталоге \Device. Драйверы, не поддерживающие Plug and Play, и драйверы файловой системы обычно создают символьную ссылку с общеизвестным именем (скажем, \Device\Hardware2). Поскольку общеизвестные имена не срабатывают в средах с динамически меняющимся составом оборудования, PnP-драйверы предоставляют один или несколько интерфейсов через функцию IoRegisterDeviceInterface, передавая ей GUID, определяющий тип предоставляемой функциональности. GUID являются 128-битными числами, которые можно генерировать с помощью утилиты Guidgen, входящей в состав DDK и Platform SDK. Диапазон чисел, который может быть представлен 128 битами, гарантирует, что каждый GUID, созданный этой утилитой, всегда будет глобально уникальным.

IoRegisterDeviceInterface определяет символьную ссылку, сопоставляемую с экземпляром объекта «устройство». Однако, прежде чем диспетчер ввода-вывода действительно создаст ссылку, драйвер должен вызвать функцию IoSetDeviceInterfaceState, чтобы разрешить использование интерфейса этого устройства. Обычно драйвер делает это, когда диспетчер PnP посылает ему команду start-device для запуска устройства.

Приложение, которому нужно открыть объект «устройство», представленный GUID-идентификатором, может вызывать PnP-функции настройки, например SetupDiEnumDeviceInterfaces для перечисления интерфейсов, доступных по конкретному GUID, и получения имен символьных ссылок, с помощью которых может быть открыт объект «устройство». Чтобы получить дополнительную информацию (например, автоматически сгенерированное имя устройства), приложение вызывает функцию SetupDiGetDeviceInterface-Detail для всех устройств, перечисленных SetupDiEnumDeviceInterfaces. Получив от SetupDiGetDeviceInterfaceDetail имя устройства, приложение обращается к Windows-функции CreateFile, чтобы открыть устройство и получить его описатель.

ЭКСПЕРИМЕНТ: просмотр каталога \Device

Для просмотра имен устройств в каталоге \Device пространства имен диспетчера объектов можно использовать утилиту Winobj (wwwsysin ternals.com) или команду !object отладчика ядра. Ниже показан пример символьной ссыпки, созданной диспетчером ввода-вывода и указывающей на объект «устройство» с автоматически сгенерированным именем.

Команда !object отладчика ядра для каталога \Device выводит следующую информацию.

Поделиться с друзьями: