С точки зрения модели драйверов windows wdk существуют драйверы следующих типов

(Redirected from Windows DDK)

«WDK» redirects here. For the ISO 639 code wdk, see Yarli language.

The Windows Driver Kit (WDK) is a software toolset from Microsoft that enables the development of device drivers for the Microsoft Windows platform.[2] It includes documentation, samples, build environments, and tools for driver developers.[3] A complete toolset for driver development also need the following: a compiler Visual Studio, Windows SDK, and Windows HLK.

Windows Driver Kit

Developer(s) Microsoft
Initial release 1992; 33 years ago
Stable release

10.1.26100.2454
/ November 27, 2024; 5 months ago[1]

Operating system Microsoft Windows
Available in English
License Proprietary commercial software
Website docs.microsoft.com/en-us/windows-hardware/drivers/index

Previously, the WDK was known as Device Development Kit (DDK)[4] for Windows 3.x and Windows 9x. It supported the development of VxD drivers. Later versions for Windows NT and Windows 98SE and ME were called Driver Development Kit (DDK)[5] and supported Windows Driver Model (WDM) development. It got its current name when Microsoft released Windows Vista and added the following previously separated tools to the kit: Installable File System Kit (IFS Kit), Driver Test Manager (DTM), though DTM was later renamed and removed from WDK again.

The DDK for Windows 2000 and earlier versions did not include a compiler; instead one had to install Visual C++ separately to compile drivers. From the version for Windows XP the DDK and later the WDK include a command-line compiler to compile drivers. One of the reasons Microsoft gave for including a compiler was that the quality of drivers would improve if they were compiled with the same version of the compiler that was used to compile Windows itself while Visual C++ is targeted to application development and has a different product cycle with more frequent changes. The WDK 8.x and later series goes back to require installing a matched version of Visual Studio separately, but this time the integration is more complete in that you can edit, build and debug the driver from within Visual Studio directly.

Version Build number Release date Supported Driver Model
Windows 3.0 DDK 1990 VxD
Windows 3.1 DDK 1992 VxD
Windows NT 3.1 DDK 1993 NTDM
Windows NT 3.5 DDK 1994 NTDM
Windows NT 3.51 DDK 1025.1 July 1995 NTDM
Windows 95 DDK October 1995 VxD
Windows 95 DDK a June 1996 VxD
Windows 95 DDK b VxD
Windows 95 DDK c (MSDN July 1998) June 1998 VxD
Windows NT DDK (for Windows NT Workstation 3.51) July 1996 NTDM
Windows NT DDK (for Windows NT Workstation 4.0) 1381.1 August 1996 NTDM
Windows 98 DDK July 1998 VxD, WDM?
Windows 98 SE DDK May 1999 VxD, WDM?
Windows 2000 DDK 2195.1 February 2000 WDM
Windows Me DDK August 7, 2000 VxD only
Windows XP Driver Development Kit (DDK) 2600 September 21, 2001 WDM
Windows XP SP1 Driver Development Kit (DDK) 2600.1106 November 14, 2002 WDM
Windows Server 2003 DDK 3790 April 9, 2003 WDM
Windows Server 2003 with Service Pack 1 DDK 3790.1830 April 6, 2005 WDM

Note: Windows NT DDK, Windows 98 DDK and Windows 2000 DDK are no longer made available by Microsoft because of Java-related settlements made by Microsoft with Sun Microsystems.[6]

Version Build number Release date Develops drivers for Visual Studio integration Notes
Windows Driver Kit for Windows Vista 6000 November 29, 2006 Windows Vista
Windows Driver Kit – Server 2008 (x86, x64, ia64) 6001.18000 January 1, 2008 Windows XP SP1 – Vista SP1, Windows Server 2000 SP4 – 2008
Windows Driver Kit – Server 2008 (x86, x64, ia64) 6001.18001 April 1, 2008
Windows Driver Kit – Server 2008 Release SP1 (x86, x64, i64) 6001.18002 December 8, 2008 Windows XP SP1 – Vista SP1, Windows Server 2000 SP4 – 2008 SP1
Windows Driver Kit 7.0.0 7600.16385.0 August 6, 2009 Windows 7, Windows Server 2008 R2
Windows Driver Kit 7.1.0 7600.16385.1 February 26, 2010 Windows XP SP3 – 7, Windows Server 2003 SP1 – 2008 R2 [7]
Windows Driver Kit 8.0 8.59.25584 August 15, 2012 Windows 7 – 8, Windows Server 2008 R2 – 2012 Visual Studio 2012 Downloads before 8/17/2012 had a bug in WDF co-installer[8]
Windows Driver Kit 8.1 8.100.26638 September 16, 2013 Windows 7 – 8.1, Windows Server 2008 R2 – 2012 R2 Visual Studio 2013[9]
Windows Driver Kit 8.1 Update 8.100.26846 August 20, 2014 Windows 7 – 8.1 Update, Windows Server 2008 R2 – 2012 R2 Visual Studio 2013
Windows Driver Kit 10, Version 1507 10.0.26639 July 2015 Windows 7 SP1 – 10 Visual Studio 2015 RTM – Update 3
Windows Driver Kit 10, Version 1511 10.0.10586 November 2015 Windows 7 SP1 – 10 Version 1511 Visual Studio 2015 Update 1 – 3 Windows 10 November Update
Windows Driver Kit 10, Version 1607 10.0.14393 August 2016 Windows 7 SP1 – 10 Version 1607 (Excludes Win10 Version 1507 & 1511) Visual Studio 2015 Update 3 Windows 10 Anniversary Update
Windows Driver Kit 10, Version 1703 10.0.15063 April 2017 Windows 7 SP1 – 10 (Version 1607 & 1703 only), Windows Server 2008 R2 – 2016 Visual Studio 2017 Ver.15.1 Windows 10 Creators Update
Windows Driver Kit 10, Version 1709 10.0.16299 October 2017 Visual Studio 2017 Ver.15.4 Windows 10 Fall Creators Update
Windows Driver Kit 10, Version 1803 10.0.17134 April 2018 Windows 10 April 2018 Update
Windows Driver Kit 10, Version 1809[10] 10.0.17763 October 2018 Windows 10 October 2018 Update
Windows Driver Kit 10, Version 1903 10.0.18362.1 April 2019 Windows 7 SP1 – 10 (Version 1607 to 1903), Windows Server 2008 R2 SP1 – 2019 Visual Studio 2019 Ver.16 Windows 10 May 2019 Update
  • Windows Driver Frameworks
  • Windows Driver Model
  • Windows Logo Kit
  1. ^ «Other WDK downloads». Microsoft Learn. Retrieved 2024-12-03.
  2. ^ Enrico Perla; Massimiliano Oldani (2010). A Guide to Kernel Exploitation; Attacking the Core. Elsevier Science. p. 277. ISBN 9781597494878.
  3. ^ BHATT, PRAMOD CHANDRA P. (2019). AN INTRODUCTION TO OPERATING SYSTEMS : CONCEPTS AND PRACTICE (GNU/LINUX AND WINDOWS), FIFTH EDITION. PHI Learning Pvt. Ltd. p. 529. ISBN 9789387472884.
  4. ^ README.TXT from Windows 3.1 Device Development Kit (DDK)
  5. ^ Bill Blunden (2009). The Rootkit Arsenal; Escape and Evasion. Jones & Bartlett Learning. p. 142. ISBN 9781449661229.
  6. ^ MSDN: Products Unavailable due to Java-related Settlement
  7. ^ [1] Windows Driver Kit Version 7.1.0
  8. ^ WDF co-installer issue
  9. ^ Kraig Brockschmidt (2014). Programming Windows Store Apps with HTML, CSS, and JavaScript. Pearson Education. p. 1002. ISBN 9780735695702.
  10. ^ Liu, Zhifeng; Zheng, Desheng; Wu, Xinlong; Chen, Jixin; Tang, Xiaolan; Ran, Ziyong (2021). VABox: A Virtualization-Based Analysis Framework of Virtualization-Obfuscated Packed Executables. International Conference on Artificial Intelligence and Security. Springer International Publishing. pp. 73–84. ISBN 9783030786212. We use Visual Studio 2017 and WDK for Windows 10, version 1809 for development.

В Windows поддерживается
несколько типов драйверов, различающихся
интерфейсом взаимодействия с системой,
назначением и решаемыми задачами.
Упрощенная классификация драйверов
Windows приведена на рис. .15.

Рис.15.
Упрощенная классификация драйверов
Windows

Драйверы пользовательского режима

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

Программы для
операционной системы DOS широко использовали
прямые обращения из пользовательских
приложений к внешним устройствам через
порты ввода-вывода и отображение
регистров устройств на адресное
пространство памяти. Но такие обращения
невозможно выполнить в защищенной
операционной системе.

Для того, чтобы
обеспечить возможность выполнения
старых программ DOS на современных версиях
Windows, в состав операционной системы
Windows включен компонент VDM, реализующий
виртуальную машину DOS.

VDM перехватывает
попытки обращения исполняемой программы
к портам ввода-вывода или регистрам,
отображенным на адресное пространство
памяти, и передает эти обращения драйверу
VDD. Драйвер VDD переадресует полученные
запросы драйверам режима ядра, используя
системный вызов DeviceIoControl, как показано
на рис. 16.

Драйверы VDD
регистрируются в реестре в разделе
VirtualDeviceDrivers:

HKLM\SYSTEM\CurrentControlSet\Control\

VirtualDeviceDrivers

В указанном разделе
реестра хранится параметр VDD,
хранящий полный путь и имя каждого
параметра в виде текстовой строки,
разделенной нулями.

Драйверы принтеров
принимают на вход задания для печати в
виде последовательности аппаратно
независимых команд языков печати PS
или PCL и переводят их
в инструкции соответствующего принтера.
Принтеры подключаются к компьютеру по
каналам LPT, USB
или по локальной вычислительной сети.
При этом передачей потока команд от
драйвера принтера к принтеру занимаются
драйверы LPT, USB
или сетевых адаптеров, в зависимости
от подключения.

Рис.16.
Драйвер виртуального устройства DOS

Драйверы режима ядра

Драйверы режима
ядра имеют прямой доступ к регистрам
внешних устройств. Windows
определяет несколько вариантов
интерфейсов для взаимодействия
операционной системы и драйвера. Как
следствие, существует несколько
разновидностей драйверов режима ядра.

Интерфейс
унаследованных драйверов не поддерживает
PnP и управление питанием. Он предназначен
для обеспечения совместимости новых
версий Windows с драйверами от Windows NT
версии 3.

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

Графические
драйверы предназначены для отображения
графической информации на экране
монитора. Существует два класса
графических драйверов: драйверы дисплея
и минипорт-драйверы видеоадаптера.

Драйверы дисплея
взаимодействуют с системой GDI. Они
получают аппаратно независимые
высокоуровневые запросы на отображение
графических примитивов и транслируют
их в низкоуровневые команды, которые
передаются минипорт-драйверу
соответствующего видеоадаптера.

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

Windows реализует
собственную сетевую среду, известную
как NDIS – Network Drivers Interface Specifications. Далее
мы рассмотрим организацию и работу NDIS
более детально.

Драйверы WDM –
Windows Driver Model являются основным (базовым)
типом драйверов устройств в Windows. В класс
WDM попадают драйверы шин, функциональные
драйверы и драйверы фильтров.

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

Функциональные
драйверы обеспечивают управление
устройствами, подключенными к шинам.
Функциональные драйверы взаимодействуют
со своими устройствами через
аппаратно-независимый интерфейс,
предоставленный драйвером шины.
Функциональные драйверы обеспечивают
для вышележащих компонентов операционной
системы аппаратно-независимый интерфейс
к контролируемым ими устройствам в
терминах записать-прочитать данные.
Кроме того, функциональные драйверы
реализуют управляющий интерфейс
(доступен через системный вызов
DeviceIoControl), позволяющий управлять
устройствами определенного класса в
терминах единой для этого класса
устройств системы команд. В качестве
примеров классов устройств могут быть
названы: беспроводные сетевые адаптеры,
стримеры, устройства долговременной
памяти с произвольным доступом,
клавиатуры, и т.п. Безусловна, система
команд должна быть различной для
устройств различного класса, но в рамках
одного класса устройств команды не
зависят от конкретной реализации
устройства, его модели, модификации,
производителя.

Драйверы фильтров
не управляют устройствами. Они
предназначены для модификации данных
в запросах ввода-вывода, направляемых
функциональным драйверам или драйверам
шины, или данных в ответах, получаемых
от них.

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

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

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

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

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

Например, фильтр
верхнего уровня для драйвера клавиатуры
может проверять дополнительный пароль,
блокируя работу клавиатуры, если пароль
введен неверно.

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

Как мы знаем, на аппаратном уровне современный компьютер состоит из функциональных узлов, представляющих собой те или иные электронные компоненты. Широкому кругу пользователей персональных компьютеров знакомы такие функциональные блоки как: процессор, память, видеокарта, звуковая карта, жесткий диск, контроллер ввода-вывода (обеспечивающий работу клавиатуры, мыши, джойстика, USB-носителей (флешек)), принтер, сканер и некоторые другие. На физическом уровне данные устройства взаимодействуют между собой посредством специальных шин и протоколов, создавая совокупностью своего взаимодействия симбиоз операций, который, в общем случае, характеризует функционирование компьютера. Но разве компьютер представляет собой только лишь набор электронных компонентов? Конечно же нет, ведь один из основных аппаратных модулей, центральный процессор, спроектирован для выполнения машинных инструкций, из последовательностей которых, как мы знаем, состоят программы, в свете этого было бы уместно упомянуть еще об одном уровне — программном.
Теперь давайте вернемся в не столько далекое прошлое; на заре компьютерной эры код программ (которые часто писались непосредственно в машинных кодах/на низкоуровневых языках) мог легко взаимодействовать с аппаратурой напрямую, поскольку аппаратная архитектура была относительно простой. Однако со временем технологии развивались, аппаратный и программный уровни эволюционировали взаимосвязано, и первый пришел к появлению большого многообразия устройств, а второй к появлению огромного разнообразия программных модулей, обусловивших, в дальнейшем, появление операционных систем. Операционная система явилась ключевой вехой в истории развития компьютерной индустрии, поскольку именно она, среди прочего, выполняла роль связующего звена, своеобразного координатора (диспетчера), обеспечившего взаимодействие между устройствами и программами: принимала запросы от программного слоя (например, пользовательских программ) на обмен данными с тем или иным устройством и наоборот, то есть фактически выполняла роль сопряжения между аппаратной и программной частями (сама являясь программной частью).
Операционные системы, в свою очередь, тоже не стояли на месте, и если по началу взаимодействие операционной системы с аппаратурой компьютера было относительно простым, то по мере усложнения архитектуры и введения новых аппаратных возможностей, усложнялась и структура операционной системы. На протяжении всего времени развития операционных систем, разработчики пытались создать код, обеспечивающий полноценное взаимодействие с максимально возможным количеством имеющимся на рынке аппаратных устройств. Тем не менее, подобный подход, по мере усложнения архитектуры персональных компьютеров x86, привел к появлению концепции обособленного программного слоя, носящего название драйвер, ответственного за взаимодействие с тем или иным классом/типом устройств. Концепция драйвера оказалась настолько удачной, что помимо основного направления — поддержки физических устройств, была экстраполирована и на некоторые категории логических/виртуальных устройств. В данной статье мы будем рассказывать про то, что же из себя представляет драйвер Windows.

Теория

Давайте на время абстрагируемся от концепции драйвера и начнем с общей теории. Для того, чтобы понять что же представляет собой драйвер в системе, сначала нужно пройти необходимый минимум теории по общей архитектуре x86-64. Почему x86, да потому что именно эта платформа: а) выбрана мной для экспериментов, б) является наиболее распространенной в клиентском сегменте операционных систем Windows. Озвученные в данном разделе особенности дадут нам понимание многих аспектов работы как непосредственно операционной системы, так и, соответственно, драйверов в её составе.

Режимы работы процессора

Внутренняя структура любой операционной системы базируется на аппаратных особенностях платформы, на которой она работает. Центральным звеном является процессор, у процессоров архитектуры x86-64 имеются несколько режимов работы:

  • Реальный режим (Real mode);
  • Виртуальный режим (Virtual mode);
  • Защищенный режим (Protected mode);
  • Длинный режим (Long mode).

На заре эры развития персональных компьютеров архитектуры x86, процессор работал в реальном режиме. Тем не менее, реальным режим постепенно ушел в прошлое, поскольку имел ряд особенностей, делающих затруднительным дальнейшее развитие технологии: однозадачную аппаратную среду, 16-битную шину данных и 20-битную шину адреса (ограничение по адресации), сегментную адресацию с размерами сегментов в 64 килобайта (неудобство использования адресного пространства), отсутствие разграничений доступа к адресному пространству (невозможность создания изоляции процессов). С целью снятия существовавших ограничений был разработан защищенный режим, который предоставлял ряд важных для развития операционных систем особенностей: многозадачность, механизм защиты (доступ к привилегированным командам), обеспечивающий контроль доступа различных участков кода (программ) друг к другу, модель виртуальной памяти. В защищенном режиме процессоров Intel архитектуры x86 реализованы так называемые кольца защиты или уровни привилегий. Всего их четыре: 0 (наиболее привилегированный), 1, 2 и 3 (наименее привилегированный). Уровни привилегий призваны защитить код режима ядра от пользовательских программ и пользовательские программы друг от друга, поскольку это может привести к нарушению работоспособности. Однако операционная система Windows не использует все перечисленные уровни, в ней задействованы лишь два из них: 0-й и 3-й.
Для наглядности понимания приведем упрощенную схему взаимодействия компонентов Windows:

Windows drivers

Как вы видите, внутренняя среда операционной системы Windows разделена на две части и поддерживает два режима выполнения:

  • Пользовательский режим — непривилегированный режим, сопоставленный с аппаратным 3-им кольцом защиты процессора;
  • Режим ядра — привилегированный режим, сопоставленный с аппаратным 0-м кольцом защиты процессора;

В этой особенности состоит самый, пожалуй, важный момент понимания внутреннего строения Windows: глобально операционная система как бы поделена на две основных части: пользовательский режим и режим ядра.

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

  • Изолированными (не пересекающимися) виртуальными адресными пространствами: пространство пользовательского режима занимает «нижнюю» часть (адреса с 00000000 по 7FFFFFFF (для 32-бит)), пространство режима ядра занимает «верхнюю» (адреса с 7FFFFFFF по FFFFFFFF (для 32-бит));
  • Разными привилегиями доступа кода к ресурсам (памяти, процессору, устройствам и прч).

В пользовательском режиме выполняются следующие процессы (пример для Windows 7):

Подсистема Описание
Процессы обеспечения работоспособности системы (System Support Processes)
  • Процесс входа в систему Winlogon (winlogon.exe)
  • Процесс локального сервера проверки подлинности lsass (lsass.exe)
  • Процесс диспетчера управления службами (services.exe)
  • Процесс диспетчера сессий (smss.exe)
  • Процесс консоли (conhost.exe)
  • Процесс диспетчера локальных сессий (lsm.exe)
  • . . .
Процессы служб/сервисов (Service Processes)
  • Хост-процесс для служб (svchost.exe)
  • Процесс диспетчера очереди печати (spoolsv.exe)
  • Процесс управления службой WMI (winmgmt.exe)
  • . . .
Приложения (Applications)
  • Пользовательские приложения (все приложения, не входящие в остальные категории).
  • Диспетчер задач (taskmgr.exe)
  • Проводник (explorer.exe)
  • Консоль управления (mmc.exe)
  • . . .
Подсистемы окружения (Environment Subsystems)
  • Подсистема Win32 (csrss.exe, kernel32.dll, advapi32.dll, user32.dll, gdi32.dll, …)
  • Подсистема Linux (lxss.sys, lxcore.sys)
  • Подсистема POSIX (psxss.exe, psxrun.exe, posix.exe, psxdll.dll)
  • Подсистема OS/2 (os2.exe, os2ss.exe, os2srv.exe)
  • Подсистема WOW/WOW64 (wow64win.dll, wow64.dll, wow64cpu.dll)
  • . . .
Интерфейс к функциям ядра
  • Обеспечивает передачу управления в ядро для функций, которым это необходимо. Поддерживается библиотекой ntdll.dll

В режиме ядра выполняются (пример для Windows 7):

Подсистема Описание
Исполнительная система (Executive)
  • Диспетчер ввода-вывода
  • Диспетчер процессов
  • Диспетчер потоков
  • Диспетчер виртуальной памяти
  • Диспетчер объектов
  • Диспетчер PnP
  • Диспетчер питания
  • Диспетчер окон
  • . . .
Ядро (Kernel) инициализация критических для системы драйверов этапа загрузки, межпроцессорная синхронизация, планирование и диспетчеризация процессов/потоков/прерываний, обработка/диспетчеризация исключений/ошибок и некоторые другие функции (ntoskrnl.exe, ntkrnlmp.exe, ntkrnlpa.exe, ntkrpamp.exe).
Драйверы устройств (Device Drivers) драйверы физических/логических/виртуальных устройств: драйверы файловых систем, сети, дисков и прч.
Оконная/графическая подсистема (Windowing And Graphics System) Подсистема поддержки окон и графики, обеспечивающая поддержку функций графического пользовательского интерфейса (Graphic User Interface, GUI). (win32k.sys)
Уровень абстрагирования от оборудования (Hardware Abstraction Layer, HAL) обеспечивает независимость от аппаратной части платформы, изолирует компоненты ядра от специфики аппаратного обеспечения. (hal.dll)

Поскольку любая операционная система попросту обязана уметь работать с аппаратными средствами, в дистрибутиве (комплекте установки/системных файлах) присутствуют драйверы ключевых компонентов аппаратного обеспечения, без которых система буквально лишится доступа к аппаратной части со всеми вытекающими из этого проблемами: не сможет функционировать или вовсе не пройдет процедуру собственной установки. Представлены эти «внутренние» драйверы в виде так называемой встроенной библиотеки драйверов, видоизменяющейся по составу от версии к версии, в зависимости от этапов эволюционирования аппаратного обеспечения и рыночных тенденций. Драйвера из состава данной библиотеки, при необходимости, устанавливаются на этапе инсталляции операционной системы в зависимости от обнаружения (идентификации) в компьютере тех или иных устройств. В общем случае, во время инсталляции, код модуля обнаружения оборудования выполняет перечисление (определение) установленных в компьютере устройств и проверяет в своей библиотеке наличие сопоставимых драйверов. Для тех устройств, для которых присутствуют системные драйвера, производится установка в автоматическом (фоновом) режиме. Тем самым «на выходе», после инсталляции операционной системы, мы можем получить минимально-необходимый для функционирования набор системных драйверов, который позволяет организовать работоспособную [начальную] рабочую среду. Но стоит помнить, что ограничиваться встроенными в дистрибутив драйверами не стоит, поскольку для полноценного функционирования большинства устройств могут потребоваться драйвера, предоставляемые производителем устройства.

Остается открытым вопрос: действительно все компоненты режима ядра взаимодействуют с оборудованием исключительно через уровень HAL? или имеются исключения? В Сети (в некоторых источниках) встречаются схемы, на которых драйвера графического адаптера взаимодействуют с видеокартами как бы «напрямую», в обход HAL. Действительно, графике в некоторых версиях Windows отводился наивысший приоритет, поэтому она была выделена в отдельную категорию устройств, работающую напрямую с графическим адаптером, и сделано это было с целью ускорения графического интерфейса системы (в ущерб стабильности).

Уровни запросов прерываний (IRQL)

Среди ключевых внутренних механизмов, определяющих функционирование операционной системы Windows, имеется достаточно важная для понимания принципов работы драйверов тема, обойти которую стороной вряд ли получится. Механизм этот носит название уровня запросов прерываний (Interrupt Request Level, IRQ Level, IRQL) и достаточно сложен для понимания, поэтому углубленное его изучение выходит далеко за рамки излагаемого материала, однако в данной статье мы предпримем попытку краткого изложения (ну а в будущем выделим под него отдельную статью). Откровенно говоря, сам я до сих пор путаюсь в концепции IRQL, поэтому буду излагать собственное понимание планомерно, шаг за шагом, с опорой на знания, полученные на каждом из этапов.
Исторически сложилось так, что термин прерывание всегда ассоциировался у меня с реальным режимом работы процессора, перенося во времена операционной системы MSDOS, когда все было достаточно просто: существовал набор из 256 прерываний, доступных через таблицу векторов прерываний. Часть этих прерываний были аппаратными, соответственно генерировались самостоятельно по каким-либо внешним аппаратурным событиям, другие же являлись программными, то есть могли вызываться из кода приложений. Записи в таблице прерываний могли переопределяться, потому как вектор обработчика прерывания был доступен для изменения по своему усмотрению на адрес собственной процедуры обработки. Таких понятий как уровень запросов прерываний не существовало, все было просто и понятно. Однако, прогресс на месте не стоял и с эволюцией процессоров и операционных систем появился сначала защищенный режим, а затем Microsoft выпустила очередную версию своих операционных систем, которая получила название Windows, и вот с этого самого момента все начало стремительно усложняться.
Буквально внезапно, в первых же версиях Windows 95/NT, возникла какая-то внутренняя таблица (состоящая из 32 уровней запросов прерываний), уровни которой градируются от самого низкого 0 (passive) до самого высокого 31 (high):

Имя Класс Назначение Уровень Intel x86-64
HIGH Аппаратный Наивысший уровень. Немаскируемое прерывание и другие типы. 31
POWER Аппаратный События сбоя питания 30
IPI Аппаратный Межпроцессорный сигнал. Сигналы межпроцессорного взаимодействия. 29
CLOCK Аппаратный Такт системного таймера 28
PROFILE Аппаратный Контроль производительности. Таймер профилирования ядра (механизм измерения производительности системы). 27
DEVICE Аппаратный DIRQL (Devices IRQL). Аппаратные прерывания устройств. 3-26
DISPATCH Программный Операции планировщика/отложенные вызовы процедур (DPC). 2
APC Программный Асинхронные вызовы процедур. 1
PASSIVE Программный Пассивный уровень. Нет прерываний. Обычный уровень выполнения кода режима пользователя 0

Как можно заметить, в приведенной таблице присутствует очень интересная особенностью: вместе сведены и программные и аппаратные уровни (0-2 это программные уровни, а с 3-31 это аппаратные). Как позднее выяснилось:

IRQL — собственный программный атрибут (введенный разработчиками Microsoft), не имеющий никакой аппаратной поддержки со стороны процессора. Система самостоятельно управляет всеми типами возникающих прерываний через механизм отображения уровней прерывания аппаратного контроллера прерываний (PIC) и собственных программных уровней в единую аппаратно-независимую таблицу уровней прерываний.

Из этого утверждения следует, что модель собственная, программная, и уровни в ней не привязаны к какой-либо спецификации оборудования, это позволяет системе собрать в единую иерархию приоритетов аппаратные и не аппаратные типы прерываний. Низшие (не аппаратные/программные) уровни IRQL (PASSIVE, APC, DPC/DISPATCH) используются для синхронизации программных подсистем операционной системы: запуска операций планирования, таких как переключение потоков или обработка завершения ввода/вывода. Давайте рассмотрим их подробно:

  • 0-й (низший) приоритет IRQL (PASSIVE): является типовым уровнем запроса прерываний, на котором производится основная работа в операционной системе (как в пользовательском режиме, так и в режиме ядра). Код (программа), выполняющийся на данном уровне, может быть элементарно прерван (вытеснен) всем чем угодно: например потоки, исполняющиеся с уровнем IRQ PASSIVE подвергаются вытеснению планировщиком по истечении кванта времени, выделенного для них.
  • 1-й уровень IRQL (APC): На этом уровне выполняются так называемые асинхронные вызовы процедур (APC). Фактически это процедуры, организующие асинхронный ввод-вывод, или обращающиеся/ждущие освобождения каких-либо (внешних, глобальных) системных объектов. То есть важная особенность их заключается в том, что они выполняются асинхронно в контексте содержащего их потока, дабы не тормозить процесс в целом. Использование APC-функций (таких как WaitForSingleObjectEx, WaitForMultipleObjects и других) в коде не приводит к мгновенному выполнению функции, вместо этого поток (в контексте которого функция выполняется) переходит в специальный статус и генерируется программное прерывание APC, вызов функции ставится во внутреннюю очередь. В следующий раз, когда подошло время выполняться этому потоку, запланированная APC-функция выполняется на уровне APC. Потоки, работающие на уровне APC, соответственно не получают запросы своего же уровня АРС, которые система использует для операций завершения ввода/вывода.
  • 2-й уровень IRQL (DPC/DISPATCH):
    • используется для обработки отложенных вызовов процедур (Deferred procedure call, DPC): Отложенные вызовы процедур — это подпрограммы обратного вызова, которые отложены для выполнения до того момента, когда произойдет переключение на уровень IRQL DISPATCH; Обычно DPC запрашиваются с высоких уровней IRQL с целью осуществления дополнительной работы, для которой затрачиваемое процессорное время не критично. Это довольно важная для производительности стадия, и сейчас я объясню почему. Драйверы устройств стараются выполнять минимально-возможное количество операций внутри собственных подпрограмм обработки прерывания (ISR), чтобы не занимать продолжительное время на уровне DIRQL (DEVICE), тем самым не блокируя остальные прерывания и не тормозя, в итоге, всю систему.

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

      Если драйвер понимает, что требуется выполнение дополнительной работы, которая занимает существенное процессорное время, то он запрашивает DPC и перекладывает на него эту задачу. Когда уровень IRQL опускается до DISPATCH, происходит обратный вызов отложенной функции драйвера, которая и выполняет оставшуюся часть обработки. Реализуя подобный алгоритм на уровне IRQL DISPATCH, драйвер проводит на уровне DIRQL меньшее количество времени, и соответственно, уменьшает время задержки на обработку собственного прерывания, тем самым освобождая его для других устройств системы.

    • используется для выполнения задач планировщика: в операционных системах линейки Windows NT реализована вытесняющая многозадачность, которая означает, что каждому процессу, выполняющемуся в операционной системе, выделяется для выполнения определенное время. Поскольку IRQL планировщика потоков и DPC равен 2, то он выше приоритета пользовательских потоков (исполняемых на уровне 0). В свою очередь приоритет планировщика ниже чем приоритет аппаратных прерываний (прерываний от устройств), то есть он может быть прерван аппаратными прерываниями.

Пример, поясняющий назначение IRQL

Хорошо, но я так и не понял, почему нельзя было отказаться от всех этих уровней и сделать «плоскую» модель очередей, либо выполнять все эти типы задач по мере поступления? Давайте смоделируем рабочую ситуацию: представим какой-либо код, например небольшую программу, написанную «на коленке». Мы запустили её на выполнение, соответственно в системе сформировался процесс для нашей программы, в контексте которого начал выполняться основной поток. Типовой поток (режима пользователя или режима ядра) исполняется на самом низшем уровне IRQL PASSIVE. На протяжении всего времени выполнения потока, часы (микросхема таймера) периодически генерирует собственные прерывания для отсчета временных интервалов, которые используются для указания операционной системе о прохождении заданного промежутка времени. Процедура обработки прерывания часов выполняется на уровне IRQL CLOCK, который (если посмотреть в таблицу) выше по приоритету большинства уровней: и уровня DISPATCH, на котором выполняется планировщик, и уровня PASSIVE, на котором выполняется наша программа. Таким образом таймер постоянно вытесняет работу и планировщика и нашей программы. С каждым переданным тиком таймера, процедура обработки прерывания таймера уменьшает остающийся у выполняющегося в данный момент нашего пользовательского потока квант времени. В момент, когда квант времени выполняющегося потока уменьшается до нуля, программа обработки прерывания часов генерирует прерывание уровня DISPATCH, тем самым вызывая запуск планировщика для выбора им следующего потока для выполнения. По факту генерирования прерывания уровня DISPATCH, процедура обработки прерывания таймера заканчивает исполнение своего кода и управление возвращается ядру системы. Ядро находит в очереди запросов следующее прерывание с наиболее приоритетным уровнем, находящееся в режиме ожидания. Каждое прерывание обслуживается по очереди. Когда все прерывания выше уровня DISPATCH обслужены, то выполняется процедура обработки прерывания уровня DISPATCH. Эта программа обработки прерывания обрабатывает список DPC и затем вызывает планировщик. Планировщик обнаруживает, что квант времени текущего потока исчерпан, то есть уменьшен до нуля, после чего Планировщик выполняет алгоритм планирования для выбора следующего потока на выполнение. Код поставленного на выполнение потока будет выполнен когда система опустится на уровень IRQL PASSIVE.

Таким образом получается, что IRQL позволяет реализовать механизм приоритетов, и, соответственно, вытесняющую многозадачность. в MSDOS не было вытесняющей многозадачности, там программы выполнялись сколь угодно долго, поскольку ОС была однозадачной (исключения составляли резиденты, висящие на определенных прерываниях). в Windows потребовалась многозадачность, и как её реализовать? а вот как раз при помощи приоритетов и вытеснения.

Теперь представьте, что вы уберете из системы иерархию уровней запросов прерываний, как в этом случае будет вести себя система? В этой ситуации было бы непонятно что и когда выполнять, система выполняла бы все поступающие задачи в порядке очереди, что привело бы к тому, что потоки запросто могли бы не дать планировщику выполниться, тем самым полностью уничтожить вытесняющую многозадачность, что повлекло бы за собой непредсказуемую работу ОС. Таким образом:

IRQL — уровень аппаратно-программной приоритизации, применяемый для синхронизации в операционных системах семейства Windows, то есть уровни IRQL являются основным методом, используемым для выстраивания по приоритетам всех действий, выполняемых в операционной системе Windows на протяжении всего цикла работы.

соответственно:

IRQL указывает приоритет кода, исполняющегося на процессоре по отношению к прерываниям и другим асинхронным (внезапным) событиям.

Назначение уровней IRQL в системе следующие:

  1. Маскировка: повышение уровня прерывания позволяет отрезать (замасировать) низлежащие уровни аппаратных прерываний на контроллере PIC. Это позволяет на время проигнорировать прерывания, возникающие на более низких уровнях, тем самым выигрывая время на выполнение процедуры обработки аппаратного прерывания на данном уровне.
  2. Аппаратная синхронизация: синхронизация данных между потоками, выполняющимися на разных процессорах/ядрах в многопроцессорной системе.
  3. Программная синхронизация: для определения когда различные APC/DPC-процедуры могут быть обслужены, для определения когда могут быть обслужены приложения пользовательского режима.

Тем самым, на глобальном уровне механизм IRQL позволяет подпрограмме операционной системы:

  • Управлять повторной входимостью (реентерабельность)
  • Гарантировать, что она может продолжать работу без приоритетного прерывания (вытеснения) некоторыми другими действиями.

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

Ну хорошо, а как это воздействует на драйвера? Мы знаем, что драйвера могут быть пользовательского режима и режима ядра, соответственно, выполняются пользовательском режиме и в режиме ядра. Отсюда следует, что:

Код драйвера может выполняться на разных уровнях IRQL.

И отсюда следует два достаточно важных вывода:

  1. Код драйвера является вытесняемым и прерываемым. Как и любой другой код в системе, он может быть прерван в любой момент по окончании выделенного кванта времени;
  2. Код драйвера должен использовать те или иные наборы системных функций в зависимости от уровня IRQL, на котором он выполняется.

Представьте ситуацию, когда код драйвера выполняется на низком уровне IRQL, модифицирует какой-либо объект (например, файл file.txt), затем другой код на более высоком уровне IRQL внезапно прерывает его выполнение и модифицирует тот же файл file.txt другими данными. Когда управление вернется к нашему драйверу, он продолжит модификацию файла своими данным, тем самым затерев данные, поступившие от другого источника. Таким образом файл войдет в рассогласованное состояние. Для решения подобных проблем были введены различные системные объекты синхронизации. Для того, что бы код уровня ядра мог модифицировать определенные типы данных, объекты взаимного исключения, он должен сперва получить владение блокировками.

Концепция драйвера

Ядро операционной системы Windows не проектировалось для самостоятельного взаимодействия с устройствами.

Соответственно выводы, следующие из этого утверждения, очевидны: для взаимодействия системы с устройствами требуются отдельные интерфейсы, возможно даже сложная совокупность нескольких интерфейсов. Концепция драйвера была разработана для решения задачи сопряжения и используется в моделях большинства современных систем, она основана на работе в адресном пространстве ядра специального кода, который обеспечивает взаимодействие ядра системы с любым типом логических/физических устройств.
Учитывая общую ориентированность ресурса, в статье мы будем освещать специфику исключительно драйверов операционной системы Windows. Итак, для драйвера Windows, как, в общем то, драйверов других операционных систем, верны следующие утверждения:

Драйвер (Driver) — программное обеспечение, при помощи которого операционная система (пользовательские программы, ядро и прочие компоненты) получают доступ к функционалу некоего физического или логического устройства.

то же, но другими словами:

Драйвер — интерфейс между кодом пользовательского режима, режима ядра и функциями физического/логического/виртуального устройства.

Одно из приведенных определений отмечает немаловажную особенность драйвера: ошибочно представлять драйвер исключительно во взаимодействии с физическим устройством, поскольку драйвер не обязательно должен предоставлять доступ к функциям какого-либо оборудования, он может обеспечивать и исключительно программные функциональные особенности. Примерами подобных решений являются драйвера, устанавливаемые в систему антивирусами, системами шифрования данных, системами мониторинга. Общий алгоритм работы любого драйвера следующий: приложения посредством функций специального пользовательского интерфейса (в Windows это Win32 API) или запросов ввода-вывода опосредовано/напрямую обращаются к функциям драйвера некоего устройства. Драйвер, в свою очередь, предоставляет доступ к функциональным особенностям интересующего устройства, а так же контролирует процесс взаимодействия между запросами приложений и непосредственно устройством. Естественно, что в драйвере должны быть определены (описаны) все принципы взаимодействия с обслуживаемым (подчиненным, собственным) устройством, должен присутствовать набор данных об управляемом объекте, инструкции (набор команд), с помощью которых системный/пользовательский код может корректно инициализировать устройство и начать с ним взаимодействие.

Загрузка драйверов при запуске операционной системы

Очень интересно было бы увидеть, на какой именно стадии загрузки операционной системы начинает загружается и начинает выполняться первый драйвер Windows? Однако в детальном изложении процесс этот достаточно нетривиален и для глубокого понимания требует реверсинга кода многих компонентов загрузки, в дополнение ко всему необходимо учитывать множество сопутствующих моментов, как то: последовательность загрузки, обусловленную зависимостью между драйверами, по причине которой драйвера могут группироваться в так называемые «группы загрузки», сама загрузка драйверов может разделяться на несколько этапов и прочее. При этом, следует учесть, что в Сети имеется большое количество материалов относительно устаревших уже операционных систем, поэтому мы попытаемся актуализировать процесс загрузки драйверов Windows на примере (наиболее близкой мне по духу) операционной системы Windows 7. И для начала не мешало бы рассказать об основных компонентах ядра Windows, активно участвующих в процессе загрузки драйверов:

  • Диспетчер (менеджер) ввода/вывода (I/O Manager) — модуль режима ядра, входящий в состав исполнительной подсистемы, управляющий процессами ввода/вывода, обеспечивающий абстракцию физических и логических устройств для пользовательских приложений и системных компонентов, связывающий приложения пользовательского режима с драйверами. Контролирует стадии процесса взаимодействия с драйверами. Весь обмен данными менеджера ввода-вывода с драйверами осуществляется через обращение к процедурам обратного вызова драйвера (callback) и передачи им стандартизованной структуры данных IRP, в которой описана вся суть обращения к драйверу;
  • Диспетчер (менеджер) Plug-and-Play (PnP Manager) — модуль режима ядра и пользовательского режима, входящий в состав исполнительной подсистемы, отвечающий за добавление, распознавание, удаление устройств в операционной системе. Часть режима ядра взаимодействует с остальными компонентами системы и драйверами в процессе установки (загрузки) программного обеспечения, необходимого для обслуживания имеющихся в системе устройств. Часть пользовательского режима отвечает за взаимодействие с программами режим пользователя (для интерактивного взаимодействия с пользователем) в ситуациях, требующих установки новых драйверов или настройки рабочих параметров в существующих. Управляет распределением аппаратных ресурсов в системе, так же умеет распознавать устройства, реагировать на их подключение/отключение, загружать соответствующие драйвера при обнаружении новых устройств;
  • Диспетчер (менеджер) управления службами (Service Control Manager, SCM) — системный процесс, ответственный за создание, удаление, запуск и остановку служб и драйверов операционной системы. Так же обеспечивает: функционирование журнала событий, поддержку технологии удалённого вызова процедур (remote procedure call, RPC);

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

  1. Bootmgr(.efi) загружает модуль winload(.efi) и передает ему управление.
  2. Winload(.efi) сканирует куст реестра HKEY_LOCAL_MACHINE\System\services и получает список всех установленных в системе драйверов. В этом кусте реестра присутствуют разделы, сопоставляемые с конечными драйверами, в них присутствуют разнообразные относящиеся к драйверам параметры, такие как Group, Start, Type, LoadOrderGroup, DependOnGroup, DependOnServices, определяющие те или иные критерии загрузки драйвера.
  3. Winload(.efi) загружает драйвера, критичные для начальной стадии загрузки/функционирования операционной системы, такие как драйвера контроллеров накопителей, драйвера файловых систем. Очевидно, что подобные драйвера имеют наивысший приоритет, поскольку создают базис для загрузки остальных драйверов, поэтому в следствии этих а так же иных причин должны находиться в памяти в момент передачи управления ядру. Соответственно, маркируются они специальным типом SERVICE_BOOT_START. Драйвера на данном этапе начинают загружаться в зависимости от групп, к которым они принадлежат.
  4. Winload(.efi) загружает непосредственно ядро из файла ntoskrnl.exe и передает ему управление.
  5. Ядро загружает Менеджер ввода-вывода и PnP-менеджер.
  6. Менеджер ввода-вывода создает глобальный каталог. Этот каталог, в дальнейшем, используется для регистрации объектов устройств.
  7. PnP-менеджер стартует драйвера, уже загруженные в память на предыдущем этапе (имеющие тип SERVICE_BOOT_START), вызывая процедуру DriverEntry каждого драйвера. На данном этапе загружаются и зависимые драйвера.
  8. PnP-менеджер строит дерево устройств системы, обходит его начиная с корня и загружает драйвера устройств, которые еще не были загружены.
  9. PnP-менеджер загружает оставшиеся незагруженными драйвера устройств, вне зависимости от значения параметра Start. Многие из подобных драйверов имеют тип SERVICE_DEMAND_START.
  10. PnP менеджер загружает драйвера расширенного функционала. К таким драйверам относятся драйвер видеоадаптера, драйвера внешних устройств, драйвера стека TCP/IP. Такие драйвера имеют тип SERVICE_SYSTEM_START.
  11. Ядро загружает Менеджер (диспетчер) управления сеансами/сессиями (Session Manager Subsystem Service, SMSS), который, в свою очередь, загружает Менеджер (диспетчер) управления службами (SCM). SCM сканирует куст реестра (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services) и на основе полученной информации монтирует внутреннюю базу данных служб/драйверов, формирует программный интерфейс для обслуживания установленных служб/драйверов. SCM загружает «автозапускаемые» не-PnP драйвера (имеющие тип SERVICE_AUTO_START), а также все драйвера, от которых они зависят.

Из всего этого алгоритма загрузки драйверов нам необходимо уяснить следующие основные правила: драйвер может быть загружен (в зависимости от стадии/класса драйвера) при помощи PnP-менеджера, либо с помощью SCM, а вот в процессе функционирования драйвера активно принимает участие Менеджер ввода-вывода.

Структура драйвера Windows

На что может быть похож драйвер по структуре? Неужели это какой-то особый класс программ, устроенных сугубо специфически? Я тоже так когда-то по наивности полагал, но если подумать, то с какой стати разработчикам операционной системы усложнять себе жизнь и изобретать новый специализированный формат образа исполняемого файла для каких-то ядерных компонентов? Намного проще адаптировать старый, давно уже отлаженный и сто раз проверенный.

Драйвер — это своего рода «библиотека режима ядра», обычный файл DLL, у которого в PE-заголовке (структура IMAGE_NT_HEADERS, подструктура OptionalHeader) значение поля Subsystem = 1 (IMAGE_SUBSYSTEM_NATIVE).

Тип подсистемы может быть задан при сборке исполняемого модуля. Сама по себе нативная подсистема характерна для приложений, которые функционируют по иным, отличным от классических, правилам: на стадии подготовки образа к исполнению им не требуется инициализация подсистемы Win32. В числе прочих подсистема native используется для кода режима ядра, коим и являются практически все драйвера.

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

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

  • Объекты. Блоки данных, содержащие записи свойств той или иной сущности операционной системы. Управляются диспетчером (менеджером) объектов. Многие объекты имеют дескрипторы (описатели), при помощи которых объект становится доступным для приложений.
  • Структуры данных. Блоки данных, содержащие записи свойств той или иной сущности операционной системы. Управляются ядром. Отличаются от объектов, однако (по инерции) так же называются объектами

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

Основное назначение функции DriverEntry состоит в том, чтобы разработчик драйвера реализовал в ней заполнение объекта (записей структуры) драйвера указателями на различные внутренние процедуры драйвера, обеспечивающие тот или иной функционал. В процедуре DriverEntry можно задавать (менять) имя объекта устройства, которое впоследствии используется приложениями для открытия дескриптора устройства и отправки пакетов запросов ввода-вывода (IRP).

Функция DriverEntry фактически является функцией глобальной инициализации и выполняется единожды на этапе загрузки драйвера. Эта функция может быть как предельно простой, так и содержать расширенный функционал (дополнительные подпрограммы), такой, например, как создание дополнительных объектов устройств, опрос устройства, дополнительные фазы конфигурации и инициализации устройств(а).
После публикации собственных функций драйвер становится «видимым» ядром операционной системы. Дабы не усложнять и без того достаточно непростую теорию, будем считать, что с точки зрения ядра Windows любое устройство является неким абстрактным «виртуальным устройством», оперирующим стандартизированным набором команд, и доступным через внутренние интерфейсы. Как было уже сказано выше, в ядре операционной системы Windows присутствует специальный модуль исполнительной системы, называемый диспетчером (менеджером) ввода-вывода, обеспечивающий единый интерфейс взаимодействия для всех драйверов режима ядра, включая драйверы физических устройств, драйверы логических устройств и драйверы файловых систем. Соответственно, система ввода-вывода ядра управляет драйверами, или можно сказать, что драйверы используют интерфейс диспетчера ввода-вывода для обеспечения функционирования в операционной системе. С дургой стороны, драйвер обеспечивает преобразование (конвертацию) «стандартных команд», поступающих от операционной системы, в команды, которые «понимает» подконтрольное ему устройство (если оно имеется), и наоборот. Менеджер ввода-вывода определяет набор (множество) стандартных процедур, которые могут быть реализованы в драйвере, поскольку:

Драйвер содержит набор процедур обратного вызова, которые обеспечивают различные стадии процесса ввода-вывода.

Для более глубокого понимания того, какие функциональные особенности может обеспечивать драйвер, давайте приведем общую схему ключевых процедур драйвера:

driver input-output

Собственно, глядя на приведенную схему, становится понятно, какие именно виды взаимодействия, а именно группы процедур должен реализовывать абстрактный драйвер Windows. Давайте теперь перечислим некоторые из этих процедур:

  • Инициализация — Менеджер ввода-вывода запускает процедуру инициализации (носит название DriverEntry), которая предназначается для проведения действий по начальной настройке объекта драйвера, регистрации всех иных процедур драйвера, конфигурированию подчиненного устройства и выполнении иных действия в интересах разработчика.
  • Добавление устройства — добавление (дополнительного) объекта «устройство». В данной процедуре драйвер обычно создает объекты «устройство» для каждого устройства, обслуживаемого драйвером. Обычно используется для Plug-and-Play драйверов.
  • Обработка — набор процедур диспетчеризации (обработки различных состояний). Открытие, закрытие, чтение, запись в устройство, обработка состояний питания, событий PnP и состояний системы, а так же некоторые иные виды взаимодействия описываются в процедурах диспетчеризации. Фактически это основные процедуры, поскольку через процедуры диспетчеризации обрабатываются типовые операции ввода-вывода.
  • Запуск (начало) ввода-вывода — вторая стадия обработки запроса ввода-вывода к устройству, непосредственно стартующая ввод-вывод устройства. Эта процедура может использоваться для начала передачи данных в/из устройства.
  • Процедура обслуживания прерывания — когда устройство генерирует прерывание, диспетчер прерываний передает управление на данную процедуру.
  • Обработка отложенных вызовов процедур — Процедура DPC берет на себя основную работу по обработке прерывания после выполнения ISR. Отложенные вызовы процедур выполняются на низких уровнях IRQL (DPC/DISPATCH) чем сама процедура ISR. Реализуется подобный алгоритм для исключения блокировки других прерываний.
  • Процедура завершения ввода-вывода — многоуровневый драйвер может иметь процедуры завершения ввода-вывод, которые уведомляют о завершении обработки IRP низкоуровневым драйвером.
  • Процедуры отмены ввода-вывода — если операции ввода-вывода могут быть прерваны, драйвер может определить одну или несколько подобных процедур. Когда драйвер получает IRP-пакет для запроса ввода-вывода, который может быть отменен, он назначает процедуру отмены IRP, и пакет IRP проходит через различные стадии обработки, которые эта процедура может изменить или убрать, если текущая операция не отменяема.
  • Процедура быстрой отправки — Драйвера, которые активно используют Менеджер кеша, такие как драйвера файловых систем, обычно предоставляют подобные процедуры для обеспечения возможности обхода ядром типовых алгоритмов обработки ввода-вывода.
  • Процедура выгрузки — должны быть реализованы в каждом драйвере, который работает (освобождают/занимают) с системными ресурсами, для того, чтобы Диспетчер ввода-вывода выгрузить драйвер из памяти.
  • Процедура предупреждения о завершении — позволяет драйверу освободить все занимаемые ресурсы при завершении работы системы.

Становится очевидным, что в процессе разработки драйвера Windows не стоит задачи реализовать весь набор описанных выше процедур, каждый драйвер уникален и разработчик волен обеспечивать собственный набор реализаций, поддерживаемых драйвером. Когда драйвер при помощи PnP-менеджера или SCM загружается в систему, диспетчер ввода-вывода создает в пространстве имен объект «драйвер» (driver object) и вызывает процедуру инициализации драйвера (обычно это DriverEntry), которая выполняет дальнейшие действия по инициализации.

Объект драйвера представляет образ загруженного драйвера в памяти ядра и через данный объект система управляет драйвером.

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

  • PnP-драйверы создают объекты «устройство» с помощью своих процедур добавления устройств, когда PnP-менеджер информирует их о присутствии управляемого ими устройства.
  • не-PnP-драйверы создают объекты «устройство» при вызове менеджером ввода-вывода их процедур инициализации.

При создании объекта типа «устройство» (device), драйверу требуется присвоить данному объекту имя. Затем этот вновь созданный объект помещается в пространство имен диспетчера объектов (Object Manager), который, как и диспетчер (менеджер) ввода-вывода, является частью исполнительной подсистемы ядра. Менеджер объектов предназначается для ведения базы всех ресурсов операционной системы, представленных в качестве объектов. Имя объекта может определяться самим драйвером в явном виде, либо генерироваться автоматически менеджером ввода-вывода. По соглашению, объекты «устройство» должны размещаться в каталоге \Device пространства имен менеджера объектов, недоступном приложениям через Win32 API. А для того, чтобы объект «устройство» стал доступным для приложений, драйвер должен создать в каталоге \GLOBAL?? символьную ссылку на имя этого объекта в каталоге \Device. Драйверы, не поддерживающие технологию Plug-and-Play, и драйверы файловой системы обычно создают символьную ссылку с общеизвестным именем (скажем, \Device\VMwareKbdFilter). Только после всех перечисленных действий драйвер становится «виден» в системе и доступен для вызова пользовательскими приложениями.

Взаимодействие с драйвером

Каким же образом пользовательская программа может взаимодействовать с драйвером в системе? На этот случай имеется два способа:

  1. Неявный — вызов типовой функции Win32 API;
  2. Явный — прямой запрос ввода-вывода к драйверу;

Ну с первым случаем все достаточно просто, в прикладной программе вызывается какая-либо ординарная функция Win32 API (например, CreateFile), которая, затем, в зависимости от целевого объекта (файла, каталога) может вызвать в цепочке своих вызовов функцию обмена с драйвером. Фактически, в этом случае код приложения не ставит своей задачей взаимодействовать с каким-либо драйвером, просто по цепочке вызовов процедур, на определенном этапе выполнение уходит в режим ядра и там происходит вызов функции драйвера. Все это остается сокрытым от разработчика, однако возможно отследить взаимодействие при помощи отладочных средств.
Второй случай более интересен, он возникает когда под вызовом драйвера подразумевается не косвенный вызов (посредством вызова типовой функции), а передача при помощи специальной функции (например, DeviceIoControl) так называемого запроса ввода/вывода (I/O control request), который, в дальнейшем, инициирует формирование блока данных под названием пакета запроса ввода-вывода.

Пакет запроса ввода-вывода (IRP, I/O Request Packet) — структура данных ядра Windows, содержащая информацию, описывающую запрос ввода-вывода.

Формально IRP это пакет, но фактически это объект ядра, то есть структура (блок) данных с набором процедур для менеджера ввода-вывода, обеспечивающая обмен данными между программой и драйвером, либо между драйвером и драйвером. Как мы уже упоминали, архитектура Windows построена таким образом, что в ней запрещено прямое взаимодействие программы режима пользователя и драйвера, поэтому подобный обмен сводится к посылке программой кода IOCTL, который уже приводит к формированию менеджером ввода-вывода IRP пакета запроса. Именно менеджер ввода-вывода, как ответственный за взаимодействие с драйверами, оперирует пакетами IRP. Менеджер ввода-вывода получается запрос на ввод-вывод от пользовательской программы, затем формирует IRP и передает его соответствующему драйверу.
Пакет IRP состоит из двух частей:

  • постоянной части;
  • стека размещения ввода-вывода.

В постоянной части IRP содержит старший и (не всегда) младший код функции. Старшие коды: IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_CLEANUP, IRP_MJ_DEVICE_CONTROL, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_SCSI, IRP_MJ_SYSTEM_CONTROL, IRP_MJ_POWER, IRP_MJ_PNP, IRP_MJ_SHUTDOWN. Пакет так же содержит стек размещения ввода-вывода — специальную структуру IO_STACK_LOCATION, содержащую определенные параметры: это набор устройств, которые обработают данный IRP пакет. Причем по стеку этот пакет передается последовательно от устройства к устройству. Более чем одно размещение стека говорит о том, что IRP может быть обработан несколькими драйверами. «Ячейки стека» IRP и предназначены для хранения «переменной» информации при хождении пакета IRP по стеку драйверов. Пакет IRP проходит по опубликованным процедурам каждого драйвера, каждая из которых извлекает из «своей» ячейки стека размещения ввода-вывода необходимую ей информацию. Процедуры драйвера традиционно называются «процедуры обратного вызова» (callback). Как мы уже упоминали, функция инициализации драйвера DriverEntry сообщает ядру (публикует) имена этих процедур и позже ядро само вызывает ту или иную процедуру при определенных обстоятельствах.
В отличие от штатной программы, драйвер не является классическим процессом со своим адресным пространством и не имеет потока исполнения. Вместо этого, функция драйвера выполняется в контексте того потока и процесса, в котором она была вызвана. Контекст (пространство выполнения кода) драйвера зависит от того, кто производит обращение (вызывает) к драйверу. Обращение может быть инициировано:

  1. Прикладной программой (программой пользовательского режима). В этом случае контекст исполнения драйвера точно известен, и он совпадает контекстом прикладной программы;
  2. Другим (сторонним) драйвером. В этом случае контекст исполнения определить сложнее, он может быть как известным, так и случайным, это зависит от контекста исполнения функции вызывающего драйвера.
  3. Аппаратным/программным прерыванием. В этом случае контекст исполнения случайный, поскольку прерывание (и, соответственно, переключение на код драйвера) может произойти при выполнении абсолютно любого кода в операционной системе.

Опять же, в отличии от штатной программы, драйвер не может вызывать стандартные функции Win32 API, может лишь оперировать доступными в ядре функциями, которые начинаются с префиксов Ex.., Hal.., Io.., Ke.., Ks.., Mm.., Ob.., Po.., Ps.., Rtl.., Se.., Zw.. и некоторых других.

Виды (типы) драйверов Windows

В процессе эволюционирования и, соответственно, усложнения драйверной концепции, драйверы начали подразделяться на категории (или типы) в зависимости от назначения. Вот основные из них:

  • Драйверы классов (Class driver) — драйверы, разработанные Microsoft для определенного класса устройств.
  • Драйверы файловых систем (File System Drivers) — драйверы, реализовывающие файловые системы на различного рода носителях информации.
  • Унаследованные драйвера (Legacy drivers) — «устаревшие» (совместимые по структуре со старыми версиями ОС) драйверы режима ядра, самостоятельно напрямую контролирующие подчиненное устройство без каких-либо дополнительных драйверов устройства. Почему они носят такое название? Потому, что это тип драйверов, сохранившийся от первых версий ОС линейки Windows NT.
  • Драйвер шины (Bus driver) — Драйверы, обеспечивающие функционал какой-либо шины компьютера (ISA,PCI,USB,IEEE1394 и прочих);
  • Фильтрующие драйверы (Filter driver) — драйверы, использующиеся для мониторинга/изменения логики другого драйвера путем работы с данными, проходящими через него.
    • Верхние фильтрующие драйверы (Upper-filter drivers) — подтип фильтрующих драйверов, находящийся выше функционального драйвера по стеку. Через верхние фильтрующие драйверы проходят все запросы, а это значит, что они могут изменять и/или фильтровать информацию, идущую к функциональному драйверу, ну и далее, возможно, к устройству. Примерами могут являться фильтр-драйвер, который отслеживает/фильтрует трафик, шифрует/перехватывает запросы чтения/записи. Такие драйверы используются в брандмауэрах.
    • Нижние фильтрующие драйверы (Lower-filter drivers) — подтип фильтрующих драйверов, находящийся ниже функционального драйвера по стеку. Через подобные нижние фильтрующие драйверы проходит, как правило, меньше запросов по сравнению с остальными фильтрующими драйверами, потому как большинство запросов выполняет и завершает сам функциональный драйвер.
  • Функциональные драйверы (Function driver) — драйверы, функционирующие самостоятельно и определяющие все аспекты, связанные с устройством.
  • PnP драйвер (PnP Driver) — драйвер, поддерживающий технологию Plug-and-Play;
  • Минидрайвер (минипорт, миникласс) (Miniport driver, Minidriver, Miniclass driver) — драйверы, которые обрабатывают задачи, связанные с конечным устройством и используют драйвера класса для управления устройством. Действуют как одна из частей пары драйверов, в которой данная категория действует как драйвера конечных устройств, выполняющая специфичные задачи устройства.

По уровню компонетизации драйверы бывают:

  • Одноуровневые — обработка ввода/вывода реализуется в рамках одного исполняемого модуля (драйвера).
  • Многоуровневые — обработчка ввода/вывода распределяется между несколькими драйверами.

PnP драйвера под Windows подразделяются на:

  • Функциональный Драйвер
  • Драйвер шины (шинный драйвер)
  • Драйвер-фильтр (фильтр-драйвер)

По режиму выполнения драйверы Windows градируются:

  • Драйвер пользовательского режима.
  • Драйвер режима ядра.

Модели драйверов

На протяжении всего времени существования операционной системы, разработчики пытались стандартизировать и упростить разработку драйверов. В следствии чего появились модели.

Модель WDM

Когда-то очень давно существовало две основных направления развития драйверной концепции Windows:

  1. в Windows 95/98 применялась модель VxD (Virtual Device Driver);
  2. в Windows NT3.51 параллельно развивалась модель NT-драйвер (драйвер в стиле NT, NT Driver).

Однако, начиная с версии Windows 98/NT4.0 разработчики предприняли попытку унифицировать (универсализировать) разработку драйверов, в следствии чего на смену упомянутым моделям пришла новая модель WDM.

WDM (Модель драйвера Windows, Windows Driver Model) — единая среда разработки (фреймворк) для драйверов устройств операционной системы Windows. Была создана для уменьшения кода стандартизации требований к драйверам.

Модель WDM являлся этапом переопределения классического стека драйвера Windows с целью обеспечения поддержки являющихся в то время революционными технологий Plug-and-Play и ACPI. Модель дает возможность загружать/выгружать драйверы «на лету», без необходимости в перезагрузке операционной системы, разрабатывать драйвера в виде расширений (фильтров) к стандартным системным драйверам, более гибко управлять энергосбережением и конфигурацией устройств и прочее.
В рамках модели WDM любое аппаратного устройство поддерживается, как минимум, двумя драйверами:

  • Функциональный драйвер (Function driver) — ответственен почти за все функциональные особенности обслуживаемого устройства: операции ввода-вывода, обработка прерывания и управление устройством;
  • Драйвер шины (Bus driver) — ответственен за обслуживание соединения между устройством и компьютером, фактически поддержкой связующей шины (например, PCI, USB и прочие).

Модель WDF

На протяжении всего времени развития, модель WDM претерпевала множество изменений, существенно разрастаясь. Начиная с Windows Vista была предпринята очередная попытка развития концепции драйвера Windows, в сущности уже существовавшей на тот момент модели WDM, результатом чего явилось новой модели (надстройки над WDM) под названием WDF.

WDF (Основа драйверов Windows, Windows Driver Foundation) — среда разработки (набор инструментальных средств), облегчающих разработку драйверов устройств для операционных систем Windows (Windows 2000 и более поздних).

Связано это было с тем неоспоримым фактом, что разработчикам не удалось достичь достаточного уровня абстракции модели WDM, а именно недостаточной интеграцией подсистемы ввода-вывода с технологией Plug-and-Play и управлением питанием. Это приводило к тому, что на разработчике драйвера лежала громадная нагрузка по синхронизации этих самых запросов ввода-вывода с событиями Plug-and-Play и запросами энергопотребления. Очевидно, требовалось дальнейшее упрощение драйверной модели. WDF пришла на смену WDM и считается наиболее современной моделью.
WDF реализует следующие возможности:

  1. «Вынесение» некоторых некритичных к режиму исполнения классов драйверов в пользовательский режим, что дало сокращение общего количества сбоев в ядре.
  2. Большая часть обработки взаимодействия подсистемы ввода-вывода с Plug-and-Play и управлением электропитанием выполняется теперь встроенными механизмами модели WDF.
  3. Предоставление новых внутренних интерфейсов модели WDF, которые позволяют абстрагироваться от более сложных для понимания системных интерфейсов; В модели WDM/legacy довольно сложно реализовать логику некоторых частей взаимодействия с драйвером, не изучив все азы сложной архитектуры ядра, WDF же позволяет автоматизировать многие виды взаимодействия; Большое количество кода при разработке WDM-драйвера теперь может быть заменено вызовами процедур WDF.
  4. Возможность создания «канонического» драйвера. Присутствие шаблонов, которые предоставляют стороннему разработчику возможность переопределения уникальных для его драйвера критериев, тем самым сокращая время на разработку.

Модель WDF подразделяется на два направления:

  • UMDF (Kernel-Mode Driver Framework) — среда разработки драйвера режима ядра.
  • KMDF (User-Mode Driver Framework) — среда разработки драйвера режима пользователя.

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

Типы драйверов

С точки зрения системы Plug and Play существуют следующие три типа драйверов.

  • Шинный драйвер обслуживает контроллер шины, адаптер, мост или любое устройство, которое имеет дочерние устройства. Шинные драйверы относятся к обязательным драйверам и обычно поставляются Microsoft. Для каждого типа шины в системе имеется собственный шинный драйвер.
  • Функциональный драйвер — это основной драйвер устройства, который предоставляет интерфейс с этим устройством. Этот драйвер является обязательным, за исключением случаев, когда ввод/вывод устройства осуществляется шинным драйвером или любыми драйверами фильтра. Функциональный драйвер устройства обычно реализуется в виде пары драйвер/мини-драйвер. В таких парах драйверов драйвер класса (обычно разрабатываемый Microsoft) обеспечивает функциональные возможности, необходимые всем устройствам этого типа, а мини-драйвер (обычно разрабатываемый фирмой — поставщиком конкретного устройства) обеспечивает специфические функциональные особенности устройства. Plug and Play Manager загружает по одному функциональному драйверу для каждого устройства.
  • Драйвер фильтра сортирует запросы ввода/вывода для шины, устройства или класса устройств. Драйверы фильтра являются необязательными и могут существовать в любом количестве, располагаясь на различных уровнях — как выше, так и ниже функционального драйвера и шинного драйвера. Обычно такие драйверы поставляются фирмами OEM или независимыми поставщиками аппаратных средств (IHV).

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

Уровни драйверов

Для каждого конкретного устройства существует два или более уровней драйвера: шинный драйвер для шины ввода/вывода (или Plug and Play Manager — для устройств, помещенных при энумерации на корневой уровень) и функциональный драйвер устройства. Помимо этого, могут присутствовать один или несколько драйверов фильтра для шины или устройства.

Объекты устройств

Драйвер создает объект устройства (device object) для каждого устройства, которым он управляет. Объект устройства представляет устройство для драйвера. С точки зрения Plug and Play, существуют три типа объектов устройств.

  • Физические объекты устройств (Physical Device Objects, PDO).
  • Функциональные объекты устройств (Functional Device Objects, FDO).
  • Объекты фильтров устройств

PDO представляют устройство на шине; каждый интерфейс прикладного программирования Plug and Play API, который ссылается на устройство, ссылается на PDO. FDO представляют функциональные возможности устройства функциональному драйверу. Объекты фильтров представляют драйвер фильтра. Эти три типа объектов устройств имеют тип DEVICE_OBJECT, но используются по-разному и могут иметь дополнительные расширения.

Дополнительные интерфейсы

Драйверы Plug and Play, предназначенные для использования в Windows 2000, Windows XP и Windows Server 2003, не ограничиваются использованием интерфейсов WDM. Драйверы могут вызывать другие интерфейсы для обеспечения поддержки наследуемых драйверов Windows NT, обнаружения аппаратных средств или других специфических функций, не предоставляемых WDM.
Обратите внимание, что если драйвер должен применяться как в Windows 98/ ME, так и в Windows 2000/XP/Server 2003, то он должен использовать только интерфейсы WDM.

Шинные драйверы WDM

Управление электропитанием и Plug and Play осуществляется при помощи шинных драйверов WDM, которые представляют собой стандартные драйверы WDM. Обратите внимание, что в этом контексте любое устройство, начиная с которого происходит энумерация других устройств, будет называться шиной. Шинный драйвер отвечает на пакеты запроса ввода/вывода (IRP) и может быть расширен за счет использования драйверов фильтров.
Шинный драйвер выполняет следующие задачи:

  • Энумерация устройств на шине
  • Динамическое извещение операционной системы о событиях на шине
  • Ответы на IRP от систем Plug and Play и управления электропитанием
  • Мультиплексирование доступа к шине (для некоторых шин)
  • Общее администрирование устройств на шине

В ходе энумерации драйвер шины идентифицирует устройства на своей шине и создает для них объекты устройств. Метод, с помощью которого драйвер идентифицирует устройства на шине, зависит от конкретной шины.
Шинный драйвер выполняет некоторые операции от имени устройств, находящихся на его шине, но обычно не обрабатывает операции чтения и записи на устройства, находящиеся на шине. (Эти операции обрабатываются функциональным драйвером.) Драйвер шины выступает в роли функционального драйвера для своего контроллера, адаптера, моста или другого устройства.
Microsoft поставляет шинные драйверы для большинства распространенных шин, в том числе: PCI, Plug and Play ISA, SCSI и USB. Прочие шинные драйверы могут поставляться независимыми поставщиками — IHV или OEM. Шинный драйвер может быть реализован как пара драйвер/мини-драйвер. В таких парах драйверов один из драйверов связан со вторым, а второй представляет собой DLL.
Драйвер ACPI выполняет роль как шинного драйвера, так и функционального драйвера. ACPI позволяет системе узнавать об устройствах, которые не имеют стандартного метода энумерации (т. е. о наследуемых устройствах), или о вновь определенных устройствах ACPI, энумерация которых должна производиться ACPI (например, о встроенных контроллерах). ACPI устанавливает драйверы фильтра верхнего уровня для устройств, функциональные возможности которых выходят за пределы стандарта для их шины. Например, если шинный драйвер PCI устанавливает графический контроллер с элементами управления электропитанием, которые не поддерживаются шиной PCI, то устройство может поддерживать дополнительные функциональные возможности, если драйвер ACPI загрузит для него высокоуровневый драйвер фильтра.

Драйверы устройств WDM

Драйверы устройств WDM обычно представляют собой пару «драйвер/мини-драйвер —• драйвер фильтра». В дополнение к предоставлению операционного интерфейса с устройством функциональные драйверы играют важную роль в системе управления электропитанием, предоставляя информацию владельцу политики для устройства о возможностях управления электропитанием и выполняя действия, относящиеся к переходам от режима энергосбережения к режиму подачи электропитания в полном объеме.

Шаблон:Translate
Windows Display Driver Model (WDDM, также WVDDM в эпоху Vista) — это архитектура графических драйверов для видеокарты под управлением Microsoft Windows, начиная с Windows Vista[1]. Она является заменой для архитектуры видеодрайверов Windows XP и нацелена на повышение производительности графики и новую функциональность[1].

WDDM предоставляет функциональность, необходимую для отображения рабочего стола и приложений с помощью диспетчера рабочего стола — диспетчера составных окон, работающего поверх Direct3D. Она также поддерживает интерфейсы новой инфраструктуры DXGI (DirectX Graphics Infrastructure), необходимые для основных операций создания и управления устройством. Спецификация WDDM требует видеокарту, поддерживающую по меньшей мере Direct3D 9, и должна реализовывать интерфейсы до Direct3D 9 для совместимости со старыми приложениями Direct3D; по желанию она может реализовывать интерфейсы для Direct3D 10/10.1 и выше.

Возможности, привнесённые моделью WDDM[]

Драйверы WDDM открывают новые функциональные области, которые не предоставлялись на унифицированной основе более ранними моделями графических драйверов:

Виртуализованная видеопамять[]

В контексте графики виртуализация означает, что отдельные процессы (в пользовательском пространстве) не могут видеть память соседних процессов даже путём вставки фальшивых команд в командный поток. Драйверы WDDM позволяют делать виртуализацию видеопамяти[2] и подстановку страниц видеопамяти в системную память. Если окажется, что доступной видеопамяти недостаточно для хранения всех видеоданных и текстур, данные, не используемые в текущий момент, перемещаются в системную память или на диск. Если вытесненные данные становятся нужны, они загружаются обратно. Виртуализация была в некоторой степени возможна в драйверах, рассчитанных на предыдущие модели построения (такие, как модель драйверов Windows XP), но это была целиком зона ответственности драйвера, а не системы.

Диспетчеризация[]

Исполняемый модуль управляет диспетчеризацией (планированием) конкурирующих между собой графических контекстов.[3] Каждый список команд помещается в очередь для исполнения графическим процессором, и может быть выгружен исполняемым модулем, если появляется более важная задача и если выполнение списка ещё не началось. Такое поведение отличается от потоков центрального процессора, где задача не может быть прервана и поэтому занять больше времени, чем нужно и заставить компьютер медленнее отвечать на запросы. Гибридный алгоритм планирования между родными и лёгкими потоками со взаимодействием потоков даёт бесшовный параллелизм. Важно заметить, что планирование — это не новая идея, но ранее была сферой ответственности разработчиков драйверов. WDDM пытается унифицировать опыт разных разработчиков, управляя выполнением задач графического процессора.

Межпроцессное совместное использование поверхностей Direct3D[]

Графическая поверхность Direct3D — это область памяти, содержащая информацию о текстурированных ячейках, используемых для просчёта двумерной или трёхмерной сцены. WDDM позволяет процессам совместно использовать поверхности Direct3D[4]. Поэтому приложение может включить ячейку, созданную другим приложением, в рассчитываемую сцену. Совместное пользование текстур процессами до WDDM было сложной задачей, поскольку требовало копирования данных из видеопамяти в системную память и назад, в видеопамять нового устройства.

Расширенная отказоустойчивость[]

Если драйвер WDDM зависнет или встретит сбой, графический стек перезапустит драйвер.[1] При сбое графической аппаратуры произойдёт перехват этого события и, если необходимо, драйвер будет перезапущен.

Драйверы для Windows XP были вольны реагировать на аппаратные сбои на своё усмотрение, либо уведомлением пользователя, либо попыткой устранить ошибку молча. С драйвером WDDM все сбои аппаратуры вызывают перезапуск драйвера, а пользователь получает всплывающее сообщение; это унифицирует поведение драйверов разных разработчиков.

Предыдущие драйверы реализовывались полностью в режиме ядра, в то время как WDDM частично реализован в пользовательском режиме. Если область пользователя даст невосстановимую ошибку, это в худшем случае неожиданно прервёт работу приложения вместо синего экрана, как это было в предыдущих моделях драйверов.

WDDM также позволяет перезапускать или вытаскивать графическую аппаратуру без надлежащей перезагрузки. На практике, обновление драйвера не должно требовать перезагрузки.

Необходима новая модель драйверов[]

Одним из основных сценариев, которые делает возможным Windows Display Driver Model, является Desktop Window Manager. Поскольку рабочий стол и окна приложений, управляемые DWM, являются приложениями Direct3D, количество открытых окон напрямую влияет на требуемый объём видеопамяти. Поскольку нет ограничения на количество открытых окон, доступной видеопамяти может оказаться недостаточно, и потребуется виртуализация. Поскольку содержимое окон, которые DWM объединяет в конечный рабочий стол, создаётся разными процессами, необходимо межпроцессное совместное использование графических поверхностей. Также, поскольку одновременно с DWM на рабочем столе могут работать другие приложения DirectX, приложения должны иметь возможность совместного доступа к графическому процессору, что требует диспетчеризации.

Однако сказанное справедливо для Майкрософтовской реализации составного рабочего стола под Windows Vista, с другой стороны, составной рабочий стол теоретически не нуждается в новой модели графических драйверов. Успешные реализации составных рабочих столов существовали до Windows Vista на других платформах, таких, как Quartz, Compiz, WindowFX. Своим подходом Microsoft попытался сделать надёжный WDDM как обобщение опыта по разным графическим процессорам от различных производителей, как стандартизацию их свойств и качеств. Программные свойства, отсутствующие у других моделей драйверов, можно было бы сделать несущественными с помощью дополнений или если бы была доступна менее ограничивающая или просто другая модель драйверов.

Ограничения[]

Новая модель драйверов требует, чтобы графическая аппаратура поддерживала, по крайней мере, Shader Model 2.0 (fixed function pipeline is now translated to 2.0 shaders). Однако, по информации Microsoft, на 2009 год только около 1—2 процентов аппаратуры использовало модель драйверов Windows XP[5], а остальные уже являются WDDM-совместимыми. Модель также требует наличия некоторых других аппаратных возможностей (по этой причине, например, аппаратура, поддерживающая SM 2.0, такая, как Intel GMA 900, не проходит сертификацию на WDDM[6]).

Одно из ограничений драйвера WDDM версии 1.0 в том, что он не поддерживает одновременно несколько драйверов в многоадаптерном многомониторном окружении. Если у многомониторной системы более одного графического адаптера, оба адаптера должны использовать один и тот же драйвер WDDM. Если используется более одного драйвера, Windows выключит один из них.[7]. У WDDM 1.1 уже нет такого ограничения.[8]

В WDDM 1.0/1.1 отсутствуют некоторые режимы, ранее обслуживавшиеся непосредственно драйвером, такие, как растяжка рабочего стола на несколько мониторов[9][10], хотя режим Dual View[11] по-прежнему доступен.[12]

WDDM 1.1[]

Windows 7 поддерживает важные дополнения к WDDM, известные как WDDM 1.1; подробности этой новой версии были раскрыты на WinHEC 2008. Новые возможности включают[5]:

  • DXGI 1.1, что характеризует возвращение аппаратного ускорения двумерного графического интерфейса пользователя для использования системой GDI[13] и Direct2D/DirectWrite (но не GDI+)
    • BitBlt, StretchBlt, TransparentBlt
    • AlphaBlend, ColorFill
    • Поддержка шрифтов ClearType
  • Интерфейс драйвера устройства Direct3D 11 (DDI)
  • DXVA-HD DDI[14]
  • Hardware video overlay DDI[15]
  • Необязательное шифрование AES 128
  • Необязательное декодирование зашифрованного графического содержимого
  • Поддержка нескольких драйверов в многоадаптерном многомониторном окружении

Аппаратное ускорение операций GDI и Direct2D/DirectWrite помогает уменьшить расход памяти в Windows 7, поскольку системе компоновки DWM больше не нужно держать копию системной памяти для всех графических поверхностей, используемых GDI/GDI+, как это было в Windows Vista.[16][17]

WDDM 1.1, Direct3D 11, Direct2D и DirectWrite также будут доступными с выходом Windows Vista Platform Update; однако, GDI/GDI+ в Vista будет по-прежнему полагаться на программный просчётШаблон:Нет АИ, и Desktop Window Manager будет продолжать использовать Direct3D 9Ex.Шаблон:Нет АИ

Драйверы WDDM 1.1 обратно совместимы со спецификацией WDDM 1.0; как драйверы 1.0, так и 1.1 можно использовать в Windows Vista с Platform Update или без него.[5]

WDDM 1.2[]

Поддерживается в Windows 8.

WDDM 1.3[]

Поддерживается в Windows 8.1.

WDDM 2.0[]

На WinHEC 2006 Microsoft говорил о своих планах сделать значительное изменение WDDM для улучшения многозадачности применительно к графическим процессорам. Согласно информации Microsoft, WDDM 1.0 позволяет выполнять лишь элементарное планирование задач с просчётом «batch queue» granularity. WDDM 2.0 и WDDM 2.1′, которые планировались после выхода Vista[18] но относительно которых Microsoft не огласил дату выхода в свет (Windows 8 поддерживает лишь WDDM 1.2), могли бы предложить вытесняющую многозадачность на уровне мелких структурных единиц и потребовали бы нового поколения графических процессоров.[19][20]

Поддерживается в Windows 10.

Примечания[]

  1. 1,0 1,1 1,2 Windows Vista Display Driver Model
  2. Graphics Memory Reporting in WDDM
  3. The role of the Windows Display Driver Model in the DWM
  4. Cross Process Resource Sharing
  5. 5,0 5,1 5,2 WHDC: Graphics Guide for Windows 7. Microsoft (12-06-2009). Архивировано из первоисточника 1 мая 2012.
  6. Intel excuse for no GMA900 WDDM driver: no «HW Scheduler» no driver, Beyond3D, October 26, 2006.
  7. MultiMonitor Support and Windows Vista. Проверено 20 октября 2007. Архивировано из первоисточника 1 мая 2012.
  8. Working With the Windows 7 Graphics Architecture: WinHEC 2008
  9. Are there Control Panel features that were available under Windows XP that are no longer available on Windows Vista?
  10. Stretched Desktop or Spanning Mode Not Available in Catalyst Control Center Under Windows Vista
  11. Description of DualView in Windows XP
  12. MultiMonitor Support and Windows Vista
  13. Windows DDK — GDI Hardware Acceleration. MSDN. Проверено 14 июня 2009. Архивировано из первоисточника 1 мая 2012.
  14. Windows DDK — DXVA-HD DDI. MSDN. Проверено 13 июня 2009. Архивировано из первоисточника 1 мая 2012.
  15. Windows DDK — Overlay DDI. MSDN. Проверено 13 июня 2009. Архивировано из первоисточника 1 мая 2012.
  16. Greg Schechter’s Blog: Redirecting GDI, DirectX, and WPF applications
  17. Engineering Windows 7 Graphics Performance
  18. WinHEC 2006: Display Driver Logistics And Testing
  19. WinHEC 2006: Windows Display Driver Model (WDDM) v2 And Beyond
  20. Ошибка скрипта: Модуля «String» не существует. Windows graphics system to be overhauledШаблон:Deadlink. APC Magazine (June 1, 2006). Проверено 2 июня 2006. Архивировано из первоисточника 15 июня 2006.

Ссылки[]

  • MSDN — WDDM Introduction
  • List of GPUs supporting WDDM
  Компоненты Microsoft Windows
Основные

Aero •
ClearType •
Диспетчер рабочего стола •
DirectX •
Панель задач
(Пуск •

Область уведомлений) •
Проводник
(Пространство имён •

Специальные папки
Ассоциации файлов) •
Windows Search
(Smart folders

iFilters) •
GDI •
WIM
SMB •
.NET Framework •
XPS •
Active Scripting
(WSH •

VBScript •
JScript) •
COM
(OLE •

DCOM •
ActiveX •
Структурированное хранилище
Сервер транзакций) •
Теневая копия
WDDM
UAA
Консоль Win32

Службы
управления

Архивация и восстановление
COMMAND.COM •
cmd.exe •
Средство переноса данных •
Просмотр событий
Установщик •
netsh.exe
PowerShell •
Отчёты о проблемах
rundll32.exe •
Программа подготовки системы (Sysprep) •
Настройка системы (MSConfig) •
Проверка системных файлов
Индекс производительности •
Центр обновления •
Восстановление системы •
Дефрагментация диска
Диспетчер задач •
Диспетчер устройств •
Консоль управления •
Очистка диска •
Панель управления
(элементы)

Приложения

Контакты •
DVD Maker
Факсы и сканирование
Internet Explorer •
Журнал
Экранная лупа •
Media Center •
Проигрыватель Windows Media •
Программа совместной работы
Центр устройств Windows Mobile
Центр мобильности •
Экранный диктор
Paint •
Редактор личных символов
Удалённый помощник
Распознавание речи
WordPad •
Блокнот •
Боковая панель •
Звукозапись
Календарь
Калькулятор
Ножницы
Почта •
Таблица символов •
Исторические:
Movie Maker •

NetMeeting •
Outlook Express •
Диспетчер программ •
Диспетчер файлов •
Фотоальбом •
Windows To Go

Игры

Chess Titans •
Mahjong Titans
Purble Place •
Пасьянсы (Косынка
Паук
Солитер) •
Сапёр
Пинбол •
Червы

Ядро ОС

Ntoskrnl.exe •
Слой аппаратных абстракций (hal.dll) •
Бездействие системы •
svchost.exe •
Реестр •
Службы •
Диспетчер управления сервисами
DLL
(формат модулей) •

PE •
NTLDR •
Диспетчер загрузки
Программа входа в систему (winlogon.exe) •
Консоль восстановления
Windows RE
Windows PE •
Защита ядра от изменений

Службы

Autorun.inf •
Фоновая интеллектуальная служба передачи
Файловая система стандартного журналирования
Отчёты об ошибках
Планировщик классов мультимедиа
Теневая копия
Планировщик задач •
Беспроводная настройка

Файловые
системы

ReFS •
NTFS
(Жёсткая ссылка

Точка соединения •
Точка монтирования
Точка повторной обработки
Символьная ссылка •
TxF •
EFS) •
WinFS •
FAT •
exFAT •
CDFS •
UDF
DFS •
IFS

Сервер

Active Directory •
Службы развёртывания •
Служба репликации файлов
DNS
Домены
Перенаправление папок
Hyper-V •
IIS •
Media Services
MSMQ
Защита доступа к сети (NAP) •
Службы печати для UNIX
Удалённое разностное сжатие
Службы удаленной установки
Служба управления правами
Перемещаемые профили пользователей •
SharePoint •
Диспетчер системных ресурсов
Удаленный рабочий стол
WSUS •
Групповая политика •
Координатор распределённых транзакций

Архитектура

NT •
Диспетчер объектов
Пакеты запроса ввода/вывода
Диспетчер транзакций ядра
Диспетчер логических дисков
Диспетчер учетных записей безопасности
Защита ресурсов
lsass.exe
csrss.exe •
smss.exe •
spoolsv.exe
Запуск

Безопасность

BitLocker
Защитник •
Предотвращение выполнения данных
Обязательный контроль целостности
Защищённый канал данных
UAC •
UIPI
Брандмауэр •
Центр обеспечения безопасности •
Защита файлов

Совместимость

Подсистема UNIX (Interix) •
Виртуальная машина DOS •
Windows on Windows •
WOW64

Шаблон:Microsoft APIs

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Registry в диспетчере задач windows 10 что это
  • Как включить защитник windows 10 через cmd
  • Intel driver and support assistant installer windows 10
  • Windows 10 disable telemetry github
  • Калибровка сенсорного монитора windows 10