Как писать драйверы для Windows

Деннис Турпитка, генеральный директор, Apriorit Inc.

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

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

Эта статья предлагает более или менее основы написания драйверов для компьютеров и, надеюсь, станет вашей отправной точкой в ​​изучении ядра Windows NT. .

Что такое драйвер?

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

По задачам:

Функциональные драйверы: Это классические драйверы, которые реализуют стандартный интерфейс доступа к устройствам (запросы ввода-вывода) (Рис. 1) . Такие драйверы обычно разрабатываются производителями устройств, например производителями видеокарт, поставщиками аудиоустройств и т. Д.

1. Структура функционального драйвера.

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

2. Структура драйвера фильтра.

Программные драйверы: Эти драйверы, в отличие от предыдущих, не участвуют в запросах на физические устройства (рис. 3) . Например, чтобы разработать приложение, которое находит скрытые процессы, вам необходимо получить доступ к объектам ядра системы, которые описывают каждый запущенный процесс. Затем вы можете разделить ваше приложение на две части. Одна часть будет работать в пользовательском режиме и обеспечивать графический интерфейс, а другая — в режиме ядра и обеспечивать доступ к данным закрытой системы.

3. Структура программного драйвера.

По контексту выполнения:

Драйверы режима ядра: эти драйверы выполняются в ядре системы и имеют доступ к закрытым данным. К ним применимо все вышеперечисленное.

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

Особенности разработки драйверов

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

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

Язык разработки для драйверов Windows выбирается в зависимости от типа драйвера:

• Компилятор Windows Driver Kit (WDK) для драйвера режима ядра поддерживает только язык C.

• Драйверы пользовательского режима написаны на C ++. Взаимодействие с WDK происходит через COM-интерфейсы.

Инструменты

Для запуска, отладки и тестирования драйвера вам потребуется следующее набор инструментов:

WDK 8.1: Библиотеки, компиляторы и образцы для разработки драйверов. Версия WDK выбирается в зависимости от целевой системы.

Microsoft Visual Studio 2013: Среда разработки.

OSR Loader: простая утилита для установки, запуска, остановки и удаления драйвера.

WinDbg: Очень простая и очень удобный отладчик, включенный в WDK.

VMWare или VirtualBox: виртуальная машина, необходимая для отладки и тестирования драйвера.

VirtualKD: Очень полезная утилита, которая помогает быстро и легко настроить виртуальную машину, такую ​​как VMWare или VirtualBox, для отладки в режиме ядра.

« Hello World ”

Теперь мы попробуем написать простой драйвер, который отображает сообщение в режиме ядра. Сначала создайте новый проект пустого драйвера WDM в Visual Studio (рис. 4) .

4. Создание нового пустого драйвера WDM в Visual Studio. (Щелкните изображение, чтобы увеличить)

Это то, что мы видим в обозревателе решений (рис. 5) :

5. Раздел обозревателя решений для пустого драйвера WDM.

Любой драйвер должен определять по крайней мере одну функцию: DriverEntry. Эта функция будет использована системой при загрузке драйвера. Для нашего простого драйвера это выглядит так (рис. 6) :

6. Код, определяющий функцию драйвера.

Как нетрудно догадаться, эта функция говорит «Привет» всему миру;) Попробуем построить проект (Рис.7) :

7. Сборка проекта.

Отлично, теперь драйвер готов к использованию.

Все файлы находятся здесь (Рис. 8) :

8. Скомпилированные файлы драйверов.

.cer: Это файл сертификата — начиная с Windows Vista, ОС не загрузить неподписанные драйверы. В нашем случае у нас есть тестовая подпись, позволяющая отлаживать только файл.

.inf: Этот файл конфигурации предназначен для установки драйвера. Мы не будем его использовать.

. pdb: Этот файл содержит информацию о функциях и переменных, необходимых для отладки.

.sys: Сам драйвер.

Давайте установим драйвер в целевой системе. Для этого нам необходимо скопировать файл Sample.sys в систему, запустить OSLOADER.exe и указать путь к драйверу (рис. 9) .

9. Установка драйвера через OSR Driver Loader. (Щелкните изображение, чтобы увеличить)

Запустите установку, нажав «Зарегистрировать службу». Теперь мы можем видеть наш драйвер в командной строке (sc query) или в реестре ( HKLM SYSTEM CurrentControlSet Services ) (Рис. 10 и 11) .

10. Команда командной строки, показывающая, что драйвер успешно установлен.

11 . Успешно установленный драйвер отображается в реестре.

Перед запуском драйвера («Запустить службу») разрешите отображение сообщения, выполнив команду « ed Kd_DEFAULT_MASK 0xF ” в отладчике . Теперь запустим драйвер (рис. 12) :

12. Запуск образца драйвера.

Поздравляем с успешным запуском вашего драйвера! Однако этот драйвер нельзя выгрузить из памяти и он будет работать до перезапуска ОС. Чтобы выгрузить драйвер, нам нужно немного изменить его код (рис. 13) :

13. Изменение кода драйвера для включения выгрузки.

Это сообщит системе, что наш драйвер может быть выгружен. Для этого необходимо выполнить SampleDriverUnload (рис. 14) .

14. Образец драйвера выгружается из ядра.

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

1. Определите структуру SAMPLE_DEVICE_EXTENSION , в которой мы будем хранить данные, необходимые для работы (рис. 15) .

15. Определение структуры SAMPLE_DEVICE_EXTENSION.

2. Задайте имя устройства (рис. 16) .

16 . Определение имени устройства.

3. Создайте DEVICE_OBJECT (рис. 17) .

17. Создание объекта устройства.

4. Создайте ссылку на устройство для приложений (рис. 18) .

18. Создание ссылки на устройство.

5. В SampleDriverUnload удалите как ссылку, так и DEVICE_OBJECT (рис. 19) .

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

6. Зарегистрируйте свои функции обработки запросов. Для этого нужно заполнить массив указателей на функции MJ (рис. 20) :

20. Заполнение массива указателей на функции MJ.

В настоящее время SampleMJDispatch просто возвращает STATUS_SUCCESS. Простая утилита от Sysinternals под названием WinObj позволяет нам увидеть результат (рис. 21) :

21. Утилита WinOdj, показывающая созданный объект устройства.

и (рис. 22) :

22. Утилита WinObj показывает ссылку на созданное приложение.

Теперь давайте попробуем связаться с драйвером. Создадим консольное приложение Win32 и выполним следующий код (рис. 23) :

23. Создание простого теста для драйвера.

Установите точку останова в отладчике на SampleMJDispatch и запустите тест. Ниже представлен стек, который показывает, как наш запрос дошел до драйвера. В этом случае был отправлен запрос IRP_MJ_CREATE (рис. 24) :

24. Тест драйвера успешно запущен в отладчике.

Переопределив определенные функции из DriverObject-> MajorFunction, мы можем писать/читать из устройства, а также выполнять определенные запросы.

Несколько слов об обработке ошибок: возврат кода ошибки из функции — обычная практика в языке C. Вызывающая процедура проверяет и обрабатывает возвращенные ошибки в соответствии с кодом. Для освобождения ресурсов в случае ошибки используется оператор goto..

Microsoft включает мощный инструмент для тестирования драйверов в дистрибутив Windows под названием Driver Verifier (команда «верификатор» в командной строке). С его помощью вы можете обнаруживать взаимоблокировки, утечки памяти, неправильно обработанные запросы и т. Д. Мы настоятельно рекомендуем вам использовать его!

Заключение

В этой статье мы рассмотрели только самые основы программных драйверов и их разработки. «Как пишутся драйверы для компьютера?» — это очень обширная и сложная тема, поскольку драйверы зависят как от оборудования, так и от системы. Каждое устройство и каждая операционная система представляют собой собственный набор проблем.

Мы рекомендуем вам читать дальше и экспериментировать в виртуальной среде. Что касается Windows API, то в сети Microsoft Software Developer Network есть все, что вам нужно. А если вас интересует разработка драйверов устройств для Linux, вы можете найти здесь хорошее руководство для начинающих.

Мы рекомендуем вам читать дальше и экспериментировать в виртуальной среде. Удачи вам в изучении глубины создания драйверов!


Raspberry Pi 3 может запускать универсальные приложения Windows в Windows 10 IoT Core.

Возможно, вы в последнее время видели больше возможностей Microsoft Windows 10 IoT. Он начался с Windows 10 IoT Core, но с тех пор расширился и включил следующие три платформы:

  • Windows 10 IoT Core, на котором работают приложения универсальной платформы Windows (UWP)
  • Windows 10 IoT Mobile Enterprise, которая запускает приложения UWP
  • Windows 10 IoT Enterprise, которая работает под управлением Windows native и UWPapps

В отличие от Windows В прошлом Windows 10 IoT Core — это подмножество Windows 10, предназначенное для запуска универсальных приложений Windows. Он доступен для бесплатной загрузки и не имеет обычного пользовательского интерфейса системы Windows 10. Он также работает на x86 и некоторых платформах ARM, таких как Raspberry Pi (см. Фото) . Лицензии на Windows IoT Mobile и Enterprise по-прежнему предоставляются OEM-производителям. Windows 10 IoT Core ориентирована на разработчиков встраиваемых систем и любителей.

Windows 10 IoT Mobile Enterprise построена на базе Windows 10 IoT Core и является прямым родственником ОС Windows 10 Mobile, используемой на телефонах Windows. Он включает в себя пользовательский интерфейс. Он также предназначен для запуска универсальных приложений Windows и может использоваться для поддержки мобильных корпоративных устройств, от сканеров штрих-кодов до панелей управления.

Windows 10 IoT Enterprise — это, по сути, семейство Windows Embedded OS, которое разработчики и OEM-производители знакомы с. Он также основан на Windows 10 IoT Core, но версия Enterprise запускает как настольные, так и универсальные приложения.

Windows 10 IoT Enterprise имеет пятилетний жизненный цикл с пятью годами расширенной поддержки. Онлайн-активация может быть отложена, и она имеет множество встроенных функций включения, таких как унифицированный фильтр записи, встроенная загрузка и вход в систему, а также средство запуска оболочки Windows.. Программное обеспечение для управления мобильными устройствами (MDM) помогает в управлении и удаленном обслуживании. Версия Enterprise поддерживает Windows Assessment and Deployment Kit (ADK) и Windows Image Configuration Designer (ICD).

Microsoft Visual Studio может работать со всеми тремя платформами IoT. Visual Studio может создавать собственные приложения x86 для Windows 10, а также универсальные приложения. Последний может быть написан на C # и Visual Basic.

Приложение UWP поддерживает все функции безопасности Windows, такие как Windows Information Protection (WIP) и строгую двухфакторную аутентификацию (2FA). Приложения также могут использовать локальные базы данных SQLite в дополнение к поддержке Entity Framework 7 для UWP.



Как мне получить начали писать драйверы устройств? [закрыто]

Я хотел бы научиться писать драйверы устройств, потому что я думаю, это было бы весело. Я использую Mac OS X Macbook, но у меня также есть компьютер с Ubuntu (работающий на Mac Min). Я хорошо знаком с C и сейчас читаю эту книгу. Я нашел несколько ссылок в Интернете, например Mac Dev Center. Я делаю это, потому что было бы весело. Я думаю, что было бы настоящим удовольствием видеть работу оборудования благодаря написанному мной программному обеспечению.

Думаю, мне бы хотелось получить несколько советов или советов, и знает ли кто-нибудь список устройств, на которых нет драйверов, или я могу написать драйвер для чего-то, что уже поддерживается ( предпочел бы первое, поэтому я действительно представляю ценность). С какого устройства лучше начать работу? Я откусываю больше, чем могу прожевать? Я не боюсь низкоуровневого программирования или сборки или каких-либо дополнительных усилий. Мне бы очень хотелось испытать себя!


Для Linux вы можете почитать книгу O’Reilly Linux Device Drivers или прочитать PDF-файлы в Интернете. На мой взгляд, это один из лучших текстов на эту тему.

Руководство по программированию модулей ядра Linux — еще один хороший ресурс.

Вы также можете почитать книгу, посвященную ядру Linux. Для этой цели я взял копию Роберта Лава «Разработка ядра Linux» (2-е издание) (готовится 3-е издание).


33

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

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

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

Улучшите этот ответ
ответил 8 февраля ’10 в 22:01
  • 12
    Не могли бы вы поделиться некоторыми подробностями. Хотелось бы понять патч и то, почему его так сложно отлаживать. Какой класс устройства был драйвером? — Anirudh 7 сен 2015 в 18:52
добавить комментарий |

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

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

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


6

Если вы хотите заняться разработкой драйверов устройств для Linux, обязательно прочтите свободно доступную книгу O’Reilly «Драйверы устройств для Linux, третье издание».

Чтобы найти неподдерживаемое оборудование, для которого вы могли бы написать драйвер, спросите в списках рассылки Linux. Может какое-нибудь устройство USB 3.0? 😉

Улучшить этот ответ
ответил 08 февр. в 18:58
  • Спасибо! Сколько работы написать драйвер устройства? Это больше или меньше работы, чем написание большого сложного приложения? — Бьорн 8 фев. 2010 в 16:33
добавить комментарий |

Если вы хотите заняться разработкой драйверов устройств для Linux, обязательно прочтите свободно доступную книгу O’Reilly «Драйверы устройств для Linux, третье издание». .

Чтобы найти неподдерживаемое оборудование, для которого вы могли бы написать драйвер, спросите в списках рассылки Linux. Может какой-нибудь USB 3. 0 устройство? 😉


2

Для Mac вам может понадобиться чтобы взглянуть на книгу Mac OS X Internals. Это сложно и сложно, но интересно читать. В основном это Mac на базе PowerPC, но есть приложение о Mac на базе Intel. Для Linux взгляните на драйверы устройств Linux, 3-е издание — он легче (бесплатные PDF-файлы онлайн 🙂 и действительно ориентирован на драйверы устройств, может быть лучшим началом.

Улучшить этот ответ
отредактировано 8 февраля 2010 г., 16:07
ответил 8 февраля ’10 в 15:57
  • Спасибо! Сколько работы написать драйвер устройства? Это больше или меньше работы, чем написание большого сложного приложения? — Бьорн, 8 фев. 2010, 16:33
  • 2
    Хм, в обоих случаях вам нужно знать, что вы делаете, поэтому вам нужно понимать окружающую среду, и это исходит из опыта, которого вы не получите, пока не попробуете 🙂 Проработайте несколько примеров из LDDv3 исходный код находится в сети, но немного устарел для текущих ядер, вы почувствуете, что в нем задействовано и что вы хотели бы изучить дальше. — Николай Фетисов 08 фев, в 16:47
добавить комментарий |

Для Mac вы можете взглянуть на книгу Mac OS X Internals. Это сложно, но интересно читать. В основном это Mac на базе PowerPC, но есть приложение о Mac на базе Intel. Для Linux обратите внимание на драйверы устройств Linux, 3-е издание — он легче (бесплатные PDF-файлы в Интернете 🙂 и действительно ориентирован на драйверы устройств, может быть лучшим началом.

Загрузите эту статью в формате .PDF
Этот тип файла включает графику и схемы с высоким разрешением, если применимо.
Оцените статью
logicle.ru
Добавить комментарий