Диспетчер устройств, доступный из оснастки Computer Management (Управление компьютером) и с вкладки Hardware (Оборудование) окна свойств системы, отображает простой список устройств в системе, сконфигурированной по умолчанию. Для просмотра устройств в виде иерархического дерева можно выбрать в меню View (Вид) диспетчера устройств команду Devices By Connection устройства по подключению). Рис. 9-26 иллюстрирует, как выглядит окно диспетчера устройств при выборе этой команды.
C учетом перечисления устройств загрузка и инициализация драйверов происходит в следующем порядке.
1. Диспетчер ввода-вывода вызывает входную процедуру каждого драйвера, запускаемого при загрузке системы. Если у такого драйвера имеются дочерние устройства, диспетчер ввода-вывода перечисляет эти устройства, сообщая о них диспетчеру PnP Дочерние устройства конфигурируются и запускаются, если их драйверы являются запускаемыми при загрузке системы. Если у устройства есть драйвер, не запускаемый при загрузке системы, диспетчер PnP создает для этого устройства узел, но не запускает устройство и не загружает его драйвер.
2. После инициализации драйверов, запускаемых при загрузке системы, диспетчер PnP проходит по дереву устройств, загружая драйверы для узлов устройств, не загруженных на первом этапе, и запускает их устройства. Запуская каждое устройство, диспетчер PnP перечисляет его дочерние устройства (если таковые есть). Для этого он запускает соответствующие драйверы и при необходимости перечисляет их дочерние устройства. Ha данном этапе диспетчер PnP загружает драйверы для обнаруженных устройств независимо om значений параметров Start этих драйверов (кроме тех драйверов, параметр Start которых содержит значение «отключен»). B конце этого этапа драйверы всех PnP-устройств загружены и запущены, кроме драйверов не перечисляемых устройств и их дочерних устройств.
3. Диспетчер PnP загружает любые еще не загруженные драйверы, запускаемые системой. Эти драйверы определяют свои устройства, не перечисляемые обычным образом, и сообщают о них. После этого диспетчер PnP загружает драйверы для этих устройств.
4. Наконец, диспетчер управления сервисами (SCM) загружает автоматически запускаемые драйверы.
Дерево устройств используется диспетчерами PnP и электропитания в то время, когда они выдают устройствам IRP-пакеты, связанные с Plug and Play и управлением электропитанием. Как правило, поток IRP распространяется от верхней части узла устройств вниз, и иногда какой-либо драйвер в одном из узлов устройств создает новые IRP для передачи другим узлам (всегда в направлении корня). O потоках IRP-пакетов, связанных с Plug and Play и управлением электропитанием, мы поговорим позже.
ЭКСПЕРИМЕНТ: получаем дамп дерева устройств
Команда !devnode отладчика ядра позволяет более подробно изучить дерево устройств. Задав O и 1 в качестве параметров, вы получите дамп внутренних структур узлов этого дерева. При этом элементы структур выводятся с отступами, отражающими позиции элементов в общей иерархии.
Информация, показываемая для каждого узла устройств, включает InstancePath (имя подраздела для перечисленного устройства в HKLM\ SYSTEM\CurrentControlSet\Enum) и ServiceName (имя подраздела для драйвера устройства в HKLM\SYSTEM\CurrentControlSet\Services). Чтобы просмотреть такие ресурсы, как прерывания, порты и диапазоны памяти, назначенные каждому узлу устройств, используйте команду !devnode 0 3.
Все устройства, обнаруженные после установки системы, регистрируются в подразделах раздела реестра HKLM\SYSTEM\CurrentControlSet\Enum. Этим подразделам присваиваются имена в виде ‹Перечислителъ›\‹ID_устройства›\‹ID_экземпляра›, где перечислитель — драйвер шины, ID_ycmpouства — уникальный идентификатор устройств данного типа, а ID_экземпляра — уникальный идентификатор данного экземпляра этого устройства.
Узел устройств, который включает минимум два объекта «устройство», показан на рис. 9-27.
• Объект «физическое устройство» (physical device object, PDO) Создается драйвером шины по заданию диспетчера PnP, когда драйвер шины, перечисляя устройства на своей шине, сообщает о наличии какого-либо устройства. PDO представляет физический интерфейс устройства.
• Необязательные группы объектов-фильтров (filter device objects, FiDO) Одна группа таких объектов размещается между PDO и FDO (создается драйверами фильтров шин), вторая — между FDO и первой группой FiDO (создается низкоуровневыми драйверами фильтров), третья — над FDO (создается высокоуровневыми драйверами фильтров).
• Объект «функциональное устройство» (functional device object, FDO) Создается функциональным драйвером, который загружается диспетчером PnP для управления обнаруженным устройством. FDO представляет логический интерфейс устройства. Функциональный драйвер может выступать и в роли драйвера шины, если к устройству, представленному FDO, подключены другие устройства. Этот драйвер часто создает интерфейс к PDO, соответствующему данному FDO, что позволяет приложениям и другим драйверам открывать устройство и взаимодействовать с ним. Иногда функциональные драйверы подразделяются на драйвер класса, порт-драйвер и минипорт-драйвер, совместно управляющие вводом-выводом для FDO.
Узлы устройств полагаются на функциональность диспетчера ввода-вывода; поток IRP идет по узлу устройств сверху вниз. Решение об окончании обработки IRP может быть принято на любом уровне узла устройств. Например, функциональный драйвер может обработать запрос на чтение, не пересылая IRP драйверу шины. IRP проходит весь путь сверху вниз и далее к узлу устройств, содержащему драйвер шины, только если функциональному драйверу нужна помощь драйвера шины.
До сих пор мы так и не ответили на два важных вопроса: как диспетчер PnP определяет, какой функциональный драйвер нужно загрузить для данного устройства и как драйверы фильтров регистрируют свое присутствие, чтобы их можно было загружать при создании узла устройств?
Ответ на оба вопроса надо искать в реестре. Перечисляя устройства, драйвер шины сообщает диспетчеру PnP идентификаторы обнаруженных устройств. Эти идентификаторы специфичны для конкретной шины. Например, для шины USB такой идентификатор состоит из идентификатора изготовителя (vendor ID, VID) и идентификатора продукта (product ID, PID), назначенного устройству изготовителем (подробнее о форматах идентификаторов устройств см. в DDK). B совокупности эти идентификаторы образуют то, что в терминологии спецификации Plug and Play называется идентификатором устройства (device ID). Диспетчер PnP также запрашивает у драйвера шины идентификатор экземпляра (instance ID), который позволяет различать отдельные экземпляры одного и того же устройства. Идентификатор экземпляра может определять устройство относительно шины (например, USB-порт) или представлять глобально уникальный дескриптор (скажем, серийный номер устройства). Идентификаторы устройства и экземпляра дают идентификатор экземпляра устройства (device instance ID, DIID), используемый диспетчером PnP для поиска раздела устройства в ветви реестра HKLM\SYSTEM\CurrentControlSet\Enum. Пример такого раздела для клавиатуры показан на рис. 9-28. B эти разделы помещаются данные, характеризующие устройство, и получаемые из INF-файла параметры Service и ClassGUID, с помощью которых диспетчер PnP находит драйверы, нужные для данного устройства.