Резюме
   Windows поддерживает большой набор функций защиты, соответствующий ключевым требованиям как правительственных организаций, так и коммерческих структур. B этой главе мы кратко рассмотрели внутренние компоненты, лежащие в основе функций защиты.
   B следующей главе мы обсудим последний из основных компонентов исполнительной системы, описываемых в этой книге, – подсистему ввода-вывода.
 

Г Л A B A 9 Подсистема ввода-вывода

 
   Подсистема ввода-вывода в Microsoft Windows состоит из нескольких компонентов исполнительной системы, которые совместно управляют аппаратными устройствами и предоставляют интерфейсы для обращения к ним системе и приложениям. B этой главе мы сначала перечислим цели разработки подсистемы ввода-вывода, повлиявшие на ее реализацию. Затем мы рассмотрим ее компоненты, в том числе диспетчер ввода-вывода, диспетчер Plug and Play (PnP) и диспетчер электропитания. Далее исследуем структуру подсистемы ввода-вывода и различные типы драйверов устройств. Мы также обсудим основные структуры данных, описывающие устройства, драйверы устройств и запросы на ввод-вывод, а потом перейдем к этапу обработки запросов на ввод-вывод. B завершение будет рассказано о том, как распознаются устройства, как устанавливаются их драйверы и как осуществляется управление электропитанием.
 
Компоненты подсистемы ввода-вывода
   Согласно целям, поставленным при разработке, подсистема ввода-вывода в Windows должна обеспечивать приложениям абстракцию устройств – как аппаратных (физических), так и программных (виртуальных или логических) – и при этом предоставлять следующую функциональность:
    (o)стандартные средства безопасности и именования устройств для защиты разделяемых ресурсов (описание модели защиты см. в главе 8);
    (o)высокопроизводительный асинхронный пакетный ввод-вывод для поддержки масштабируемых приложений;
    (o)сервисы для написания драйверов устройств на высокоуровневом языке и упрощения их переноса между разными аппаратными платформами;
    (o)поддержку многоуровневой модели и расширяемости для добавления драйверов, модифицирующих поведение других драйверов или устройств без внесения изменений в них;
    (o)динамическую загрузку и выгрузку драйверов устройств, чтобы драйверы можно было загружать по требованию и не расходовать системные ресурсы без необходимости;
    (o)поддержку Plug and Play, благодаря которой система находит и устанавливает драйверы для нового оборудования, а затем выделяет им нужные аппаратные ресурсы;
    (o)управление электропитанием, чтобы система и отдельные устройства могли переходить в состояния с низким энергопотреблением;
    (o)поддержку множества устанавливаемых файловых систем, в том числе FAT, CDFS (файловую систему CD-ROM), UDF (Universal Disk Format) и NTFS (подробнее о типах и архитектуре файловых систем см. в главе 12).
    (o)поддержку Windows Management Instrumentation (WMI) и средств диагностики, позволяющую управлять драйверами и вести мониторинг за ними через WMI-приложения и сценарии. (Описание WMI см. в главе 4.) Для реализации этой функциональности подсистема ввода-вывода в Windows состоит из нескольких компонентов исполнительной системы и драйверов устройств (рис. 9-1).
    (o)Центральное место в этой подсистеме занимает диспетчер ввода-вывода; он подключает приложения и системные компоненты к виртуальным, логическим и физическим устройствам, а также определяет инфраструктуру, поддерживающую драйверы устройств.
    (o)Драйвер устройства, как правило, предоставляет интерфейс ввода-вывода для устройств конкретного типа. Такие драйверы принимают от диспетчера ввода-вывода команды, предназначенные управляемым ими устройствам, и уведомляют диспетчер ввода-вывода о выполнении этих команд. Драйверы часто используют этот диспетчер для пересылки команд ввода-вывода другим драйверам, задействованным в реализации интерфейса того же устройства и участвующим в управлении им.
    (o)Диспетчер PnP работает в тесном взаимодействии с диспетчером ввода-вывода и драйвером шины(bus driver) – одной из разновидностей драйверов устройств. Он управляет выделением аппаратных ресурсов, а также распознает устройства и реагирует на их подключение или отключение. Диспетчер PnP и драйверы шины отвечают за загрузку соответствующего драйвера при обнаружении нового устройства. Если устройство добавляется в систему, в которой нет нужного драйвера устройства, компоненты исполнительной системы, отвечающие за поддержку PnP, вызывают сервисы установки устройств, поддерживаемые диспетчером PnP пользовательского режима.
    (o)Диспетчер электропитания, также в тесном взаимодействии с диспетчером ввода-вывода, управляет системой и драйверами устройств при их переходе в различные состояния энергопотребления.
    (o)Процедуры поддержки Windows Management Instrumentation (WMI) (Инструментарий управления Windows), образующие провайдер WDM (Windows Driver Model) WMI, позволяют драйверам устройств выступать в роли провайдеров, взаимодействуя со службой WMI пользовательского режима через провайдер WDM WMI. (Подробнее о WMI см. раздел «Windows Management Instrumentation главы 4.)
    (o)Реестр служит в качестве базы данных, в которой хранится описание основных устройств, подключенных к системе, а также параметры инициализации драйверов и конфигурационные настройки (см. главу 4).
    (o)Для установки драйверов используются INF-файлы; они связывают конкретное аппаратное устройство с драйвером, который берет на себя ведущую роль в управлении этим устройством. Содержимое INF-файла состоит из инструкций, описывающих соответствующее устройство, исходное и целевое местонахождение файлов драйвера, изменения, которые нужно внести в реестр при установке драйвера, и информацию о зависимостях драйвера. B САТ-файлах хранятся цифровые подписи, которые удостоверяют файлы драйверов, прошедших испытания в лаборатории Microsoft Windows Hardware Quality Lab (WHQL).
    (o)Уровень абстрагирования от оборудования (HAL) изолирует драйверы от специфических особенностей конкретных процессоров и контроллеров прерываний, поддерживая API, скрывающие межплатформенные различия. B сущности HAL является драйвером шины для тех устройств на материнской плате компьютера, которые не контролируются другими драйверами.
 
Диспетчер ввода-вывода
    Диспетчер ввода-вывода(I/O manager) определяет модель доставки запросов на ввод-вывод драйверам устройств. Подсистема ввода-вывода управляется пакетами. Большинство запросов ввода-вывода представляется пакетами запросов ввода-вывода(I/O request packets, IRP), передаваемых от одного компонента подсистемы ввода-вывода другому. (Как вы еще убедитесь, исключением является быстрый ввод-вывод, при котором IRP не используются.) Подсистема ввода-вывода позволяет индивидуальному потоку приложения управлять сразу несколькими запросами на ввод-вывод. IRP – это структура данных, которая содержит информацию, полностью описывающую запрос ввода-вывода (подробнее об IRP см. раздел «Пакеты запросов ввода-вывода» далее в этой главе).
   Диспетчер ввода-вывода создает IRP (представляющий операцию ввода-вывода), передает указатель на IRP соответствующему драйверу и удаляет пакет по завершении операции ввода-вывода. Драйвер, получивший IRP, выполняет указанную в пакете операцию и возвращает IRP диспетчеру ввода-вывода, чтобы тот либо завершил эту операцию, либо передал пакет другому драйверу для дальнейшей обработки.
   Диспетчер ввода-вывода не только создает и уничтожает IRP, но и содержит общий для различных драйверов код, который они используют при обработке ввода-вывода. Благодаря этому драйверы стали проще и компактнее. Так, одна из функций диспетчера ввода-вывода позволяет драйверу вызывать другие драйверы. Этот диспетчер также управляет буферами запросов ввода-вывода, таймаутами драйверов и регистрирует, какие устанавливаемые файловые системы загружаются в операционную систему. Драйверы устройств могут вызывать около сотни функций, предоставляемых диспетчером ввода-вывода.
   Диспетчер ввода-вывода также предоставляет гибкие сервисы ввода-вывода, на основе которых подсистемы окружения (например, Windows и POSIX) реализуют свои функции. B их число входят весьма изощренные сервисы асинхронного ввода-вывода, которые дают возможность разработчикам создавать высокопроизводительные масштабируемые серверные приложения.
   Унифицированный модульный интерфейс драйверов позволяет диспетчеру ввода-вывода вызывать любой драйвер, ничего не зная о его структуре и внутреннем устройстве. Операционная система обрабатывает запросы на ввод-вывод так, будто они адресованы файлам; драйвер преобразует запросы к виртуальному файлу в запросы, специфичные для устройства. Драйверы также могут вызывать друг друга (через диспетчер ввода-вывода), обеспечивая многоуровневую независимую обработку запросов на ввод-вывод.
   Кроме обычных функций для открытия, закрытия, чтения и записи подсистема ввода-вывода Windows предоставляет ряд дополнительных функций, например для асинхронного, прямого и буферизованного ввода-вывода, а также для ввода-вывода по механизму «scatter/gather»* (см. раздел «Типы ввода-вывода» далее в этой главе).
   * Механизм, позволяющий интерпретировать, записывать и считывать физически нелинейную область памяти как единое целое. – Прим. перев.
 
Типичная обработка ввода-вывода
   Большинство операций ввода-вывода не требует участия всех компонентов подсистемы ввода-вывода. Как правило, запрос на ввод-вывод выдается приложением, выполняющим соответствующую операцию (например, чтение данных с устройства); такие операции обрабатываются диспетчером ввода-вывода, одним или несколькими драйверами устройств и HAL.
   Как уже упоминалось, в Windows потоки выполняют операции ввода-вывода над виртуальными файлами. Операционная система абстрагирует все запросы на ввод-вывод, скрывая тот факт, что конечное устройство ввода-вывода может и не быть устройством с файловой структурой. Это позволяет обобщить интерфейс между приложениями и устройствами. Таким образом, виртуальный файл относится к любому источнику или приемнику ввода-вывода (файлу, каталогу, именованному каналу и почтовому ящику), который рассматривается как файл. Все считываемые или записываемые данные представляются простыми потоками байтов, направляемыми в виртуальные файлы. Приложения пользовательского режима (к какой бы подсистеме они ни относились – Windows или POSIX) вызывают документированные функции, которые в свою очередь обращаются к внутренним функциям подсистемы ввода-вывода для чтения/записи файла и для выполнения других операций. Запросы, адресованные виртуальным файлам, диспетчер ввода-вывода динамически направляет соответствующим драйверам устройств. Базовая схема обработки запроса на ввод-вывод показана на рис. 9-2.
 
    Рис. 9-2. Схема обработки типичного запроса на ввод-вывод
   Далее мы детальнее рассмотрим эти компоненты, исследуем различные типы драйверов устройств, рассмотрим их структуру, загрузку, инициализацию и обработку запросов на ввод-вывод. Кроме того, мы обсудим роль и функциональность диспетчеров PnP и электропитания.
 
Драйверы устройств
   Для интеграции с диспетчером ввода-вывода и другими компонентами подсистемы ввода-вывода драйвер устройства должен быть написан в соответствии с правилами, специфичными для управляемого им типа устройств и для его роли в управлении такими устройствами. Здесь мы познакомимся с типами драйверов устройств, поддерживаемых Windows, и исследуем внутреннюю структуру драйвера устройства.
 
Типы драйверов устройств
   Windows поддерживает множество типов драйверов устройств и сред их программирования. Среды программирования могут различаться даже для драйверов одного типа – в зависимости от типа устройства, для которого предназначен драйвер. Драйверы могут работать в двух режимах: в пользовательском или в режиме ядра. Windows поддерживает несколько типов драйверов пользовательского режима:
    (o) Драйверы виртуальных устройств (virtual device drivers, VDD)
   Используются для эмуляции 16-разрядных программ MS-DOS. Они перехватывают обращения таких программ к портам ввода-вывода и транслируют их в вызовы Windows-функций ввода-вывода, передаваемые реальным драйверам устройств. Поскольку Windows является полностью защищенной операционной системой, программы MS-DOS пользовательского режима не могут напрямую обращаться к аппаратным средствам – они должны делать это через драйверы устройств режима ядра.
    (o) Драйверы принтеровДрайверы подсистемы Windows, которые транслируют аппаратно-независимые запросы на графические операции в команды, специфичные для принтера. Далее эти команды обычно направляются драйверу режима ядра, например драйверу параллельного порта (Parport.sys) или драйверу порта принтера на USB-шине (Usb-print.sys).
   B этой главе основное внимание уделяется драйверам устройств, работающим в режиме ядра. Эти драйверы можно разбить на несколько основных категорий.
    (o) Драйверы файловой системыПринимают запросы на ввод-вывод и выполняют их, выдавая более специфические запросы драйверам устройств массовой памяти или сетевым драйверам.
    (o) PnP-драйверыДрайверы, работающие с оборудованием и интегрируемые с диспетчерами электропитания и PnP. B их число входят драйверы для устройств массовой памяти, видеоадаптеров, устройств ввода и сетевых адаптеров.
    (o) Драйверы, не отвечающие спецификации Plug and PlayТакже называются расширениями ядра. Расширяют функциональность системы, предоставляя доступ из пользовательского режима к сервисам и драйверам режима ядра. Они не интегрируются с диспетчерами PnP и электро-
   питания. K ним, в частности, относятся драйверы протоколов и сетевого API. Драйвер Regmon, описанный в главе 4, тоже входит в эту категорию. Категория драйверов режима ядра подразделяется на группы в зависимости от модели, на которой они основаны, и их роли в обслуживании запросов к устройствам.
 
WDM-драйверы
   Это драйверы устройств, отвечающие спецификации Windows Driver Model (WDM). WDM требует от драйверов поддержки управления электропитанием, Plug and Play и WMI. Большинство драйверов Plug and Play построены как раз на модели WDM. Эта модель реализована в Windows, Windows 98 и Windows Millennium Edition, поэтому WDM-драйверы этих операционных систем совместимы на уровне исходного кода, а во многих случаях и на уровне двоичного кода. Существует три типа WDM-драйверов.
    (o) Драйверы шинУправляют логическими или физическими шинами. Примеры шин – PCMCIA, PCI, USB, IEEE 1394, ISA. Драйвер шины отвечает за распознавание устройств, подключенных к управляемой им шине, оповещение о них диспетчера PnP и управление параметрами электропитания шины.
    (o) Функциональные драйверыУправляют конкретным типом устройств. Драйверы шин представляют устройства функциональным драйверам через диспетчер PnP Функциональным считается драйвер, экспортирующий рабочий интерфейс устройства операционной системе. Как правило, это драйвер, больше других знающий о функционировании определенного устройства.
    (o) Драйверы фильтровЗанимающие более высокий логический уровень, чем функциональные драйверы, они дополняют функциональность или изменяют поведение устройства либо другого драйвера. Так, утилиту для перехвата ввода с клавиатуры можно реализовать в виде драйвера фильтра клавиатуры, расположенного на более высоком уровне, чем функциональный драйвер клавиатуры.
 
   B WDM ни один драйвер не отвечает за все аспекты управления конкретным устройством. Драйвер шины определяет изменения в составе устройств на шине (при подключении и отключении устройств), помогает диспетчеру PnP в перечислении устройств на шине, обращается к специфичным для шины регистрам и в некоторых случаях управляет электропитанием подключенных к шине устройств. K аппаратной части устройства обычно обращается только функциональный драйвер.
 
    ПРИМЕЧАНИЕB Windows 2000, Windows XP и Windows Server 2003 уровень HAL играет несколько иную роль, чем в Windows NT. До Windows 2000 сторонним поставщикам оборудования, которым нужно было добавить поддержку аппаратных шин, не поддерживаемых самой операционной системой, приходилось разрабатывать собственный HAL. Windows 2000, Windows XP и Windows Server 2003 позволяют сторонним разработчикам реализовать поддержку таких шин в виде драйверов шин.
 
Многоуровневые драйверы
   Поддержка индивидуального устройства часто распределяется между несколькими драйверами, каждый из которых обеспечивает часть функциональности, необходимой для нормальной работы устройства. Кроме WDM-драйверов шин, функциональных драйверов и драйверов фильтров, оборудование могут поддерживать и следующие компоненты.
    (o) Драйверы классов устройств (class drivers)Реализуют обработку ввода-вывода для конкретного класса устройств, например дисковых устройств, ленточных накопителей или приводов CD-ROM, где аппаратные интерфейсы стандартизированы и один драйвер может обслуживать аналогичные устройства от множества производителей.
    (o) Порт-драйверы (port drivers)Обрабатывают запросы на ввод-вывод, специфичные для определенного типа порта ввода-вывода, например SCSI. Порт-драйверы реализуются как библиотеки функций режима ядра, а не как драйверы устройств.
    (o) Минипорт-драйверы (miniport drivers)Преобразуют универсальные запросы ввода-вывода к порту конкретного типа в запросы, специфичные для адаптера конкретного типа, например для SCSI-адаптера. Минипорт-драйверы являются истинными драйверами устройств, которые импортируют функции, предоставляемые порт-драйвером. Вот пример, который демонстрирует, как работают драйверы устройств. Драйвер файловой системы принимает запрос на запись данных в определенное место конкретного файла. Он преобразует его в запрос на запись определенного числа байтов по определенному «логическому» адресу на диске. После этого он передает этот запрос (через диспетчер ввода-вывода) простому драйверу диска. Последний в свою очередь преобразует запрос в физический адрес на диске (цилиндр/дорожка/сектор) и позиционирует головки дискового устройства для записи данных. Эта схема действий показана на рис. 9-3.
 
   Эта схема иллюстрирует разделение труда между двумя драйверами. Диспетчер ввода-вывода получает запрос на запись, в котором адрес записи относителен началу конкретного файла. Далее диспетчер ввода-вывода передает запрос драйверу файловой системы, который преобразует информацию запроса в адрес начала записи на диске и число байтов, которые нужно записать на диск. Драйвер файловой системы передает через диспетчер ввода-вывода запрос драйверу диска, который транслирует его в физический адрес на диске и переносит нужные данные.
   Поскольку все драйверы – и устройств, и файловой системы – предоставляют операционной системе одинаковую инфраструктуру, в их иерархию легко добавить еще один драйвер, не изменяя существующие драйверы или подсистему ввода-вывода. Например, введя соответствующий драйвер, можно логически представить несколько дисков как один большой диск. Такой драйвер, кстати, имеется в Windows – он обеспечивает поддержку отказоустойчивых дисков. (Хотя этот драйвер присутствует во всех версиях Windows, поддержка отказоустойчивых дисков доступна лишь в серверных версиях Windows.) Драйвер диспетчера томов вполне логично размещается между драйверами файловой системы и дисков, как показано на рис. 9-4. Подробнее о драйверах диспетчера томов см. в главе 10.
 
    ЭКСПЕРИМЕНТ: просмотр списка загруженных драйверов
   Вы можете увидеть список зарегистрированных драйверов в системе Windows 2000 ,перейдя в раздел Drivers (Драйверы) оснастки Computer Management (Управление компьютером) в Microsoft Management Console (MMC) (Консоль управления Microsoft) или щелкнув правой кнопкой мыши значок My Computer (Мой компьютер) на рабочем столе и выбрав из контекстного меню команду Manage (Управление). Оснастка Computer Management также доступна в подменю Administrative Tools (Администрирование). Чтобы добраться до раздела Drivers в Computer Management, последовательно раскройте узлы System Tools (Служебные программы), System Information (Сведения о системе) и Software Environment (Программная среда), как показано ниже.
   B Windows XP и Windows Server 2003 можно получить ту же информацию, запустив утилиту Msinfo32.exe из диалогового окна Run (Запуск программы). Выберите System Drivers (Системные драйверы) в Software Environment (Программная среда) для вывода списка драйверов, сконфигурированных в системе. Te из них, которые загружены на данный момент, помечены словом «Yes» (Да) в столбце Started (Работает).
   Список загруженных драйверов режима ядра можно просмотреть и с помощью Process Explorer ( wwwsysinternals.com ).Запустите Process Explorer, укажите процесс System и выберите DLLs из подменю Lower Pane в меню View. Process Explorer перечисляет загруженные драйверы, их имена, информацию о версиях, включая название компании и описание, а также адрес загрузки (предполагается, что вы настроили отображение соответствующих столбцов в окне Process Explorer).
   Наконец, если вы изучаете аварийный дамп (или «снимок» работающей системы) с помощью отладчика ядра, то можете получить аналогичные сведения командой Im kv:
 
Структура драйвера
   Выполнением драйверов устройств управляет подсистема ввода-вывода. Драйвер устройства состоит из набора процедур, вызываемых на различных этапах обработки запроса ввода-вывода. Основные процедуры драйвера показаны на рис. 9-5.
    (o) Инициализирующая процедураДиспетчер ввода-вывода выполняет инициализирующую процедуру драйвера (которая обычно называется DriverEntry)при загрузке этого драйвера в операционную систему. Данная процедура регистрирует остальные процедуры драйвера в диспетчере ввода-вывода, заполняя соответствующей информацией системные структуры данных, и выполняет необходимую глобальную инициализацию драйвера.
    (o) Процедура добавления устройстваТакие процедуры реализуются в драйверах, поддерживающих Plug and Play. Через эту процедуру диспетчер PnP посылает драйверу уведомление при обнаружении устройства, за которое отвечает данный драйвер. Выполняя эту процедуру, драйвер обычно создает объект «устройство», представляющий аппаратное устройство.
    (o) Процедуры диспетчеризацииЭто основные функции, предоставляемые драйвером устройства, например для открытия, закрытия, чтения, записи и реализации других возможностей устройства, файловой системы или сети. Диспетчер ввода-вывода, вызванный для выполнения операции ввода-вывода, генерирует IRP и обращается к драйверу через одну из его процедур диспетчеризации.
    (o) Процедура инициации ввода-выводаC помощью этой процедуры драйвер может инициировать передачу данных как на устройство, так и с него. Эта процедура определяется лишь в драйверах, использующих поддержку диспетчера ввода-вывода для помещения входящих запросов в очередь. Диспетчер ввода-вывода ставит в очередь IRP для драйвера, гарантируя одновременную обработку им только одного IRP Большинство драйверов обрабатывают сразу несколько IRP, но создание очереди имеет смысл для некоторых драйверов, в частности для драйвера клавиатуры.
    (o) Процедура обслуживания прерываний (ISR)Когда устройство генерирует прерывание, диспетчер прерываний ядра передает управление этой процедуре. B модели ввода-вывода Windows процедуры ISR работают на уровне DIRQL (Device IRQL), поэтому они выполняют минимум действий во избежание слишком продолжительной блокировки прерываний более низкого уровня (подробнее об IRQL см. главу 3). Для выполнения остальной части обработки прерывания ISR ставит в очередь DPC (deferred procedure call), выполняемый при более низком IRQL (уровня «DPC/ dispatch»). ISR имеются лишь в драйверах устройств, управляемых прерываниями, – например в драйвере файловой системы ISR нет.
    (o) DPC-процедура обработки прерыванийDPC-процедура выполняет основную часть обработки прерывания, оставшуюся после выполнения ISR. Она работает при более низком IRQL (уровня «DPC/dispatch»), чем ISR, чтобы не блокировать без необходимости другие прерывания. DPC-процедура инициирует завершение текущей операции ввода-вывода и выполнение следующей операции ввода-вывода из очереди на данном устройстве. У многих драйверов устройств имеются процедуры, не показанные на рис. 9-5.
    (o) Одна или несколько процедур завершения ввода-выводаУ драйвера могут быть процедуры завершения ввода-вывода, уведомляющие его об окончании обработки IRP драйвером более низкого уровня. Например, диспетчер ввода-вывода вызывает процедуру завершения ввода-вывода драйве-
   pa файловой системы, когда драйвер устройства заканчивает передачу данных в файл или из него. Эта процедура уведомляет драйвер файловой системы об удачном или неудачном завершении операции или о ее отмене, а также позволяет драйверу файловой системы освободить ресурсы.
    (o) Процедура отмены ввода-выводаЕсли операция ввода-вывода может быть отменена, драйвер определяет одну или более процедур отмены ввода-вывода. Получив IRP для запроса ввода-вывода, который может быть отменен, драйвер связывает с IRP процедуру отмены. Если поток, выдавший запрос на ввод-вывод, завершается до окончания обработки запроса или отменяет операцию (например, вызовом Windows-функции