Из чего состоит драйвер
Существует два основных типа драйверов Microsoft Windows:
Драйверы пользовательского режима выполняются в пользовательском режиме и обычно предоставляют интерфейс между приложениями Win32 и драйверами в режиме ядра или другими компонентами операционной системы.
Например, в Windows Vista все драйверы принтера выполняются в пользовательском режиме. Дополнительные сведения о компонентах драйвера принтера см. в разделе "Общие сведения о печати".
Драйверы в режиме ядра выполняются в режиме ядра в рамках руководства, который состоит из компонентов операционной системы в режиме ядра, которые управляют ввод-выводом, Plug and Play памятью, процессами и потоками, безопасностью и т. д. Драйверы в режиме ядра обычно многоуровневы. Как правило, драйверы более высокого уровня обычно получают данные от приложений, фильтруют данные и передают их в драйвер более низкого уровня, поддерживающий функциональные возможности устройства.
Некоторые драйверы в режиме ядра также являются драйверами WDM, которые соответствуют модели драйвера Windows (WDM). Все драйверы WDM поддерживают Plug and Play и управление питанием. Драйверы WDM совместимы с исходным кодом (но не совместимы с двоичными файлами) в операционных системах Windows 98/Me и Windows 2000 и более поздних версий.
Как и сама операционная система, драйверы в режиме ядра реализуются как дискретные модульные компоненты, имеющие четко определенный набор необходимых функциональных возможностей. Все драйверы в режиме ядра предоставляют набор системных стандартных подпрограмм драйверов.
На следующем рисунке драйверы режима ядра делятся на несколько типов.
Как показано на рисунке, существует три основных типа драйверов в режиме ядра в стеке драйверов: самый высокий, промежуточный и самый низкий. Каждый тип немного отличается структурой, но значительно отличается в функциональных возможностях:
Драйверы самого высокого уровня. Драйверы верхнего уровня включают драйверы файловой системы (FSD), поддерживающие файловые системы, такие как:
Таблица выделения файлов (FAT)
Файловая система CD-ROM (CDFS)
Драйверы самого высокого уровня всегда зависят от поддержки базовых драйверов нижнего уровня, таких как драйверы функций промежуточного уровня и драйверы аппаратной шины самого низкого уровня.
Промежуточные драйверы, такие как виртуальный диск, зеркальное отображение или драйвер класса для конкретного типа устройства. Промежуточные драйверы зависят от поддержки базовых драйверов нижнего уровня. Промежуточные драйверы подразделяются следующим образом:
Драйверы функций управляют конкретными периферийными устройствами на шине ввода-вывода.
Драйверы фильтров вставляют себя выше или ниже драйверов функций.
Драйверы шины программного обеспечения представляют набор дочерних устройств, к которым могут подключаться все еще более высокий уровень класса, функции или фильтры.
Например, драйвер, который управляет многофункциональным адаптером с набором разнородных устройств, является драйвером программной шины.
Любой системный драйвер класса , экспортируемый системным интерфейсом класса или миникласса, фактически является промежуточным драйвером с одним или несколькими связанными драйверами миникласса (иногда называемыми мини-drivers). Каждая связанная пара классов или мини-driver предоставляет функциональные возможности, эквивалентные драйверу функции или драйверу программной шины.
Драйверы низкого уровня управляют шиной ввода-вывода , к которой подключены периферийные устройства. Драйверы низкого уровня не зависят от драйверов нижнего уровня.
Драйверы аппаратной шины предоставляются системой и обычно управляют динамически настраиваемыми автобусами ввода-вывода.
Драйверы аппаратной шины работают с диспетчером Plug and Play для настройки и перенастройки системных аппаратных ресурсов для всех дочерних устройств, подключенных к шинам ввода-вывода, управляемым драйвером. Эти аппаратные ресурсы включают сопоставления для запросов памяти устройства и прерываний (IRQ). (Драйверы аппаратной шины подразделяют некоторые функциональные возможности, предоставляемые компонентом HAL в выпусках операционной системы на основе Windows NT до Windows 2000.)
Устаревшие драйверы , которые напрямую управляют физическим устройством, являются драйверами низкого уровня.
Как уважаемый хабрапользователь наверняка знает, «драйвер устройства» — это компьютерная программа управляющая строго определенным типом устройства, подключенным к или входящим в состав любого настольного или переносного компьютера.
Основная задача любого драйвера – это предоставление софтового интерфейса для управления устройством, с помощью которого операционная система и другие компьютерные программы получают доступ к функциям данного устройства, «не зная» как конкретно оно используется и работает.
Обычно драйвер общается с устройством через шину или коммуникационную подсистему, к которой подключено непосредственное устройство. Когда программа вызывает процедуру (очередность операций) драйвера – он направляет команды на само устройство. Как только устройство выполнило процедуру («рутину»), данные посылаются обратно в драйвер и уже оттуда в ОС.
Любой драйвер является зависимым от самого устройства и специфичен для каждой операционной системы. Обычно драйверы предоставляют схему прерывания для обработки асинхронных процедур в интерфейсе, зависимом от времени ее исполнения.
Любая операционная система обладает «картой устройств» (которую мы видим в диспетчере устройств), для каждого из которых необходим специфический драйвер. Исключения составляют лишь центральный процессор и оперативная память, которой управляет непосредственно ОС. Для всего остального нужен драйвер, который переводит команды операционной системы в последовательность прерываний – пресловутый «двоичный код».
Как работает драйвер и для чего он нужен?
Основное назначение драйвера – это упрощение процесса программирования работы с устройством.
Он служит «переводчиком» между хардовым (железным) интерфейсом и приложениями или операционными системами, которые их используют. Разработчики могут писать, с помощью драйверов, высокоуровневые приложения и программы не вдаваясь в подробности низкоуровневого функционала каждого из необходимых устройств в отдельности.
Как уже упоминалось, драйвер специфичен для каждого устройства. Он «понимает» все операции, которые устройство может выполнять, а также протокол, с помощью которого происходит взаимодействие между софтовой и железной частью. И, естественно, управляется операционной системой, в которой выполняет конкретной приложение либо отдельная функция самой ОС («печать с помощью принтера»).
Если вы хотите отформатировать жесткий диск, то, упрощенно, этот процесс выглядит следующим образом и имеет определенную последовательность: (1) сначала ОС отправляет команду в драйвер устройства используя команду, которую понимает и драйвер, и операционная система. (2) После этого драйвер конкретного устройства переводит команду в формат, который понимает уже только устройство. (3) Жесткий диск форматирует себя, возвращает результат драйверу, который уже впоследствии переводит эту команду на «язык» операционной системы и выдает результат её пользователю (4).
Как создается драйвер устройства
Для каждого устройства существует свой строгий порядок выполнения команд, называемой «инструкцией». Не зная инструкцию к устройству, невозможно написать для него драйвер, так как низкоуровневые машинные команды являются двоичным кодом (прерываниями) которые на выходе отправляют в драйвер результат, полученный в ходе выполнения этой самой инструкции.
При создании драйвера для Линукса, вам необходимо знать не только тип шины и ее адрес, но и схематику самого устройства, а также весь набор электрических прерываний, в ходе исполнения которых устройство отдает результат драйверу.
Написание любого драйвера начинается с его «скелета» — то есть самых основных команд вроде «включения/выключения» и заканчивая специфическими для данного устройства параметрами.
И чем драйвер не является
Часто драйвер устройства сравнивается с другими программами, выполняющими роль «посредника» между софтом и/или железом. Для того, чтобы расставить точки над «i», уточняем:
- Драйвер не является интерпретатором, так как не исполняется напрямую в софтовом слое приложения или операционной системы.
- Драйвер не является компилятором, так как не переводит команды из одного софтового слоя в другой, такой же.
Ну и на правах рекламы – вы всегда знаете, где скачать новейшие драйвера для любых устройств под ОС Windows.
Многие считают что самому создать драйвер для Windows это что-то на грани фантастики. Но на самом деле это не так. Конечно, разработка драйвера для какого-то навороченного девайса бывает не простой задачей. Но ведь тоже самое можно сказать про создание сложных программ или игр. В разработке простого драйвера нет ничего сложного и я попытаюсь на примерах это показать.
Сперва нам нужно определится в чем мы же будем создавать наш первый драйвер. Поскольку материал ориентирован на новичков, то язык программирования был выбран один из простых, и это не Си или ассемблер, а бейсик. Будем использовать один из диалектов бейсика — PureBasic. Из коробки он не обучен создавать драйверы, но у него удачный набор файлов, используемых для компиляции и небольшое шаманство позволяет добавить эту возможность. Процесс компиляции состоит из нескольких этапов. Если кратко, то он происходит следующим образом: Сначала транслятор «перегоняет» basic-код в ассемблер, который отдается FASM'у (компилятор ассемблера), который создает объектный файл. Далее в дело вступает линкер polink, создающий исполняемый файл. Как компилятор ассемблера, так и линкер могут создавать драйверы и если немного изменить опции компиляции, то получим не исполняемый файл, типа EXE или DLL, а драйвер режима ядра (SYS).
Окно IDE с загруженным кодом драйвера показано на скрине.
Компиляция драйвера выполняется через меню «Компилятор» (это если кто не понял).
Теперь определимся что будет делать наш первый драйвер. Обычно при изучении программирования начинают с простых вещей, скажем, выполнения математических операций и вывода результата. Вот пусть наш драйвер делает тоже самое, ведь банальная математика производимая в режиме ядра это очень круто!
Может показаться что это куча бессмысленного кода, но это не так.
У каждого драйвера должна быть точка входа, обычно у нее имя DriverEntry() и выполнена она в виде процедуры или функции. Как видите, в этом драйвере есть такая процедура. Если посмотрите на начало кода, то в первых строках увидите как ей передается управление. В этой процедуре происходит инициализация драйвера. Там же назначается процедура завершения работы драйвера, которая в нашем случае имеет имя UnloadDriver(). Процедуры CreateDispatch() и CloseDispatch() назначаются обработчиками соединения и отсоединения проги из юзермода.
Процедура DeviceIoControl() будет обрабатывать запросы WinAPI функции DeviceIoControl(), являющейся в данном драйвере связью с юзермодом. В конце кода расположена так называемая ДатаСекция (DataSection), в которой находятся имена драйвера, сохраненные в формате юникода (для этого использована одна из фишек ассемблера FASM).
Видите сколько понадобилось кода для выполнения простейшей математической операции — сложения двух чисел?
А теперь рассмотрим программу, работающую с этим драйвером. Она написана на том же PureBasic.
Процедура Plus() осуществляет связь с драйвером. Ей передаются хэндл, доступа к драйверу и слагаемые числа, которые помещаются в структуру и указатель на указатель которой, передается драйверу. Результат сложения чисел будет в переменной «Result».
Далее следует код простейшего GUI калькулятора, скопированного из википедии.
Когда закроют окно, то перед завершением работы программы, закрывается связь с драйвером и производится его деинсталляция из системы.
Результат сложения чисел 8 и 2 на скриншоте.
Исходные коды драйвера и программы, можно найти в папке «Examples», PureBasic на файлопомойке, ссылку на который давал в начале статьи. Там так же найдете примеры драйвера прямого доступа к порам компа и пример работы с памятью ядра.
PS.
Помните, работа в ядре чревата мелкими неожиданностями аля, BSOD (синий экран смерти), поэтому экспериментируйте осторожно и обязательно всё сохраняйте перед запуском драйвера.
Сложно дать одно точное определение для драйвера термина. В самом фундаментальном смысле драйвер — это программный компонент, который позволяет операционной системе и устройству взаимодействовать друг с другом.
Например, предположим, что приложению необходимо считывать некоторые данные с устройства. Приложение вызывает функцию, реализованную операционной системой, а операционная система вызывает функцию, реализованную драйвером. Драйвер, написанный той же компанией, которая разработала и произвела устройство, знает, как взаимодействовать с оборудованием устройства для получения данных. После того как драйвер получает данные с устройства, он возвращает данные в операционную систему, которая возвращает его приложению.
Расширение определения
Наше объяснение до сих пор слишком упрощено несколькими способами:
Не все драйверы должны быть написаны компанией, которая разработала устройство.
Во многих случаях устройство разработано в соответствии с опубликованным стандартом оборудования. Это означает, что драйвер может быть написан корпорацией Майкрософт, и конструктор устройств не должен предоставлять драйвер.
Не все драйверы взаимодействуют напрямую с устройством.
Для заданного запроса ввода-вывода (например, для чтения данных с устройства) часто существует несколько драйверов, многоуровневые в стеке драйверов, которые участвуют в запросе. Обычный способ визуализации стека — с первым участником вверху и последним участником внизу, как показано на этой схеме. Некоторые драйверы в стеке могут участвовать, преобразовав запрос из одного формата в другой. Эти драйверы не взаимодействуют напрямую с устройством; они просто управляют запросом и передают запрос вместе с драйверами, которые ниже в стеке.
Драйвер функции: один драйвер в стеке, который напрямую взаимодействует с устройством, называется драйвером функции.
Драйвер фильтра: драйверы, выполняющие вспомогательную обработку, называются драйверами фильтров.
Дополнительные сведения о стеках см. в разделе "Стеки драйверов".
Некоторые драйверы фильтров отслеживают и записывают сведения о запросах ввода-вывода, но не участвуют в них активно. Например, некоторые драйверы фильтров выполняют роль проверяющих, чтобы убедиться, что другие драйверы в стеке правильно обрабатывают запрос ввода-вывода.
Мы могли бы расширить определение драйвера , сказав, что драйвер является любым программным компонентом, который наблюдает или участвует в обмене данными между операционной системой и устройством.
Драйверы программного обеспечения
Расширенное определение является достаточно точным, но по-прежнему неполным, так как некоторые драйверы вообще не связаны с каким-либо аппаратным устройством.
Например, предположим, что необходимо написать средство, которое имеет доступ к основным структурам данных операционной системы, доступ к которым можно получить только с помощью кода, выполняемого в режиме ядра. Это можно сделать, разделив средство на два компонента. Первый компонент выполняется в пользовательском режиме и представляет пользовательский интерфейс. Второй компонент выполняется в режиме ядра и имеет доступ к данным основной операционной системы. Компонент, который выполняется в пользовательском режиме, называется приложением, а компонент, который выполняется в режиме ядра, называется драйвером программного обеспечения. Программный драйвер не связан с аппаратным устройством.
На этой схеме показано приложение в пользовательском режиме, взаимодействующее с драйвером программного обеспечения в режиме ядра.
Драйверы программного обеспечения всегда выполняются в режиме ядра. Основной причиной написания драйвера программного обеспечения является получение доступа к защищенным данным, доступным только в режиме ядра. Однако драйверам устройств не всегда требуется доступ к данным и ресурсам в режиме ядра. Поэтому некоторые драйверы устройств работают в пользовательском режиме.
Дополнительные сведения о режимах процессора см. в разделе "Режим пользователя" и "Режим ядра".
Водители автобуса
Существует категория водителя, который мы еще не упомянули, водитель автобуса. Чтобы понять драйверы шины, необходимо понять узлы устройств и дерево устройств.
Сведения о деревьях устройств, узлах устройств и драйверах шины см. в разделе "Узлы устройств" и "Стеки устройств".
Дополнительные возможности драйверов функций
Наше объяснение до сих пор упрощает определение драйвера функции. Мы сказали, что драйвер функции для устройства является одним драйвером в стеке, который взаимодействует напрямую с устройством. Это верно для устройства, которое подключается непосредственно к шине взаимодействия периферийных компонентов (PCI). Драйвер функции для устройства PCI получает адреса, сопоставленные с ресурсами порта и памяти на устройстве. Драйвер функции напрямую взаимодействует с устройством, записывая их на эти адреса.
Однако во многих случаях устройство не подключается непосредственно к шине PCI. Вместо этого устройство подключается к адаптеру шины узла, подключенного к шине PCI. Например, USB-тостер подключается к адаптеру шины узла (называемому контроллером USB-узла), который подключен к шине PCI. Usb-тостер имеет драйвер функции, а контроллер узла USB также имеет драйвер функции. Драйвер функции для тостера косвенно взаимодействует с тостером, отправив запрос драйверу функции для контроллера узла USB. Драйвер функции для контроллера узла USB затем взаимодействует напрямую с оборудованием контроллера узла USB, который взаимодействует с тостером.
Пакет драйверов включает все программные компоненты, которые необходимо предоставить, чтобы обеспечить поддержку устройства с Windows. Как правило, пакет драйверов содержит следующие компоненты:
Ниже приведено краткое описание каждого компонента пакета драйверов.
WDK включает различные примеры пакетов драйверов. Дополнительные сведения см. в статье примеры файлов установки устройства .
INF-файл
Каждый пакет драйверов должен содержать INF-файл, который компонент установки устройства считывает при установке устройства. INF-файл не является сценарием установки. Это текстовый файл в кодировке ASCII или Unicode (только UTF-16), который предоставляет сведения об устройстве и драйвере, включая файлы драйверов, записи реестра, идентификаторы устройств, файлы каталогови сведения о версии, необходимые для установки пакета драйверов на устройстве.
Точное содержимое и формат INF-файла зависят от класса установки устройства , который в INF-файле объявляется как в. Сводка разделов INF описывает сведения, необходимые для каждого типа INF-файла. Как правило, сведения для каждого производителя находятся в разделе " модели INF". Записи в разделе Models ссылаются на разделы inf ддинсталл , содержащие сведения, относящиеся к конкретной модели.
средство инфвериф , которое предоставляется в каталоге \tools набора драйверов Microsoft Windows Driver Kit (WDK), проверяет синтаксис и структуру всех разделов и директив в перекрестных классах вместе с расширениями класса для всех классов установки, за исключением принтеров.
начиная с Windows 2000, можно использовать один файл INF для установки во всех версиях операционной системы Windows. Дополнительные сведения см. в разделе Создание INF-файлов для нескольких платформ и операционных систем. Если устройство будет продаваться на международном рынке, следует создать международный INF-файл. В зависимости от того, какие из них используются, Международный INF-файл может быть файлом в кодировке Юникод (UTF-16), а не ASCII.
Хорошим способом создания INF-файла для драйвера является изменение одного из примеров, предоставляемых WDK. Большинство образцов драйверов WDK включают INF-файлы в тот же каталог, что и образец драйвера.
Дополнительные сведения о файлах INF см. в разделе Создание INF-файла, документация по инфвериф, документация для конкретного устройства в WDK и файлы INF, прилагаемые к примерам драйверов для устройств, аналогичных вашим.
Файл каталога
Файл каталога драйверов содержит криптографический хэш каждого файла в пакете драйверов. Windows использует эти хэши для проверки того, что пакет не был изменен после его публикации. Чтобы гарантировать, что файл каталога не изменяется, он должен быть подписан цифровой подписью, которая будет доверенной для систем, использующих этот пакет драйверов.
поставщик получает цифровые подписи выпуска, отправляя свой пакет драйверов в лабораторию оборудования Windows для тестирования и подписывания. WHQL возвращает пакет с файлом каталога (. Cat ). Дополнительные сведения см. в разделе подписи выпуска WHQL.
INF-файл должен ссылаться на файл каталога с помощью директивы каталогфиле в разделе версии INF INF.
Файлы драйвера
В большинстве случаев пакет драйверов будет содержать одну или несколько служб драйверов, которые должны быть частью стека устройств для устройства, на котором установлен пакет драйверов. Дополнительные сведения о службах драйверов см. в разделе Выбор модели драйвера. Служба драйверов является частью пакета, который предоставляет интерфейс ввода-вывода для устройства. Как правило, драйвер — это библиотека динамической компоновки (DLL) с. расширение имени файла sys . Длинные имена файлов допускаются, за исключением драйверов загрузки.
Программное обеспечение, необходимое для поддержки определенного устройства, зависит от функций устройства и шины или порта, к которому он подключается. Корпорация Майкрософт поставляется с драйверами для многих распространенных устройств. Если устройство может обслуживаться одним из этих драйверов, может потребоваться написать только минидривердля конкретного устройства. Минидривер обрабатывает специфические для устройства функции от имени драйвера, предоставляемого системой. Для некоторых типов устройств даже минидривер не требуется. Например, модемы обычно поддерживаются только с файлами установки.
Другие файлы
Пакет драйверов также может содержать другие файлы, такие как параметры калибровки оборудования, служба Win32, значок устройства или файл библиотеки драйверов (например, для видеодрайверов). Дополнительные сведения см. в следующей статье:
Читайте также: