Основы функционирования драйверов в операционных системах Windows

March 11, 2012 by admin Комментировать »

Начнем с того, что в операционных системах Windows все физические устройства условно разделяются на две большие группы: поддерживающие  технологию PnP или не поддерживаю щие ее. Соответственно, драйверы, поддерживающие технологию PnP, называют WDM драй верами, а драйверы, не поддерживающие эту технологию – NT драйверами.  Это весьма упро щенный подход, но при первоначальном изучении данной темы этого достаточно. Оба типа драйверов в своей основе используют одни и те же функции, но WDM драйвер включает ряд дополнительных функций, позволяющих реализовать возможности  технологии PnP (установ ка удаление без перезагрузки, управление энергопотреблением и т. д.). Кроме  того, для уста новки  и обновления WDM драйвера устройства используется стандартный мастер Windows, знакомый всем пользователям (рис. 7.4):

Рис. 7.4

Мастер обновления

WDM драйвера устройства

Для установки/обновления WDM драйвера требуется наличие INF–файла, в котором опи

саны характеристики  драйвера (имя файла, место установки,  данные о производителе  и т. д.).

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

Основы функционирования драйверов

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

Это весьма упрощенное описание структуры драйвера, но оно дает представление о том, как работает драйвер устройства. Жизненный цикл функционирования драйвера устройства можно разделить (условно) на три этапа:

1)   инициализацию;

2)   выполнение операций по запросам операционной системы на ввод вывод данных

(Менеджер ввода вывода);

3)   остановка и удаление из системы.

Вначале драйвер устройства должен быть проинициализирован.  Процесс инициализации в упрощенном виде показан на рис. 7.5:

Рис. 7.5

Схема инициализации драйвера устройства

Драйвер  устройства записан  на диске в формате файла с расширением .sys. Для опера ционных систем Windows общепринято располагать файлы драйверов в катклоге windows\ system32\drivers, хотя это вовсе не обязательно. Сведения об установленных драйверах хра

нятся в  системном  реестре Windows  в ключе \registry\machine\system\currentcontrolset\ services. Исторически  сложилось так, что записи  о системных службах и драйверах хранятся в одном и том же разделе реестра (services). Помимо всего прочего записи содержат тип за пуска драйвера – по нему система определяет, когда нужно загружать  драйвер. Здесь есть очень важный момент: при испытаниях работоспособности драйвера желательно не инициа лизировать драйвер в момент загрузки  системы, иначе можно вообще не загрузиться, если в драйвере имеется какая либо ошибка.

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

файла в защищенную область памяти и передает управление функции DriverEntry. Основная задача этой функции – проинициализировать поля структур DriverObject и DeviceObject и выпол нить привязку  устройства к пространству имен операционной системы, чтобы можно было обращаться к устройству из программы пользователя. Кроме этого, здесь же инициализиру ется массив  указателей  на функции  вида  IRP_MJ_XXX, где XXX обозначает операцию.

Например, указатель IRP_MJ_CREATE может ссылаться на функцию, которая будет вызы

ваться при создании (открытии) устройства (например, функцией CreateFile() из программы пользователя). Каждый драйвер может включать различные функции, в зависимости от на значения устройства. Например, в устройство можно только записывать данные, но нельзя читать – в этом случае можно  не определять  функцию  для IRP_MJ_READ или сделать ее в виде программной  «заглушки».

Как в драйвере выбираются функции, которые должны выполнять в данный момент опе

рацию с устройством? Для этого предусмотрен механизм пакетов запроса ввода вывода (I/O Request  Packet,  IRP). Например,  если программа  пользователя  выполняет  запись  данных в устройство при помощи WINAPI функции WriteFile(), то Менеджер ввода вывода операцион ной системы  формирует  пакет  запроса  IRP_MJ_WRITE и посылает его драйверу устройства для выполнения. В свою очередь, драйвер устройства вызывает функцию, чей адрес указан при инициализации массива указателей и передает ей управление. Любой NT драйвер, тем не менее, должен обязательно включать обработчики пакетов запроса IRP_MJ_CREATE (откры тие устройства)  и IRP_MJ_CLOSE (закрытие устройства).

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

Взаимодействие драйвера устройства с программой пользователя рассмотрим на приме

ре чтения данных из устройства ввода вывода (рис. 7.6).

На этом рисунке показана  в упрощенном виде операция чтения данных устройства из приложения  пользователя. Приложение пользователя вызывает  функцию ReadFile(), переда вая ей дескриптор открытого устройства. Затем Менеджер ввода вывода, работающий в ре жиме  ядра, по дескриптору устройства определяет, для какого  драйвера следует формиро вать запрос  IRP_MJ_READ и подготавливает пакет запроса. Далее вызывается функция обра ботки, соответствующая полученному запросу, которая выполняет необходимые действия по чтению данных из устройства. Здесь нужно отметить, что даже драйвер никогда не выполняет напрямую операций с портами ввода вывода устройства, а передает управление уровню ап паратных абстракций, реализованному в виде библиотечных функций в библиотеке hal.dll. Фактически  здесь «заканчивается» аппаратная  «независимость» всех операций и операции проводятся на уровне конкретных аппаратных средств.

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

Рис. 7.6

Чтение данных из приложения пользователя

Таким образом, мы, в общем, рассмотрели схему работы NT подобного драйвера устрой ства. Здесь не анализируются другие важнейшие  аспекты функционирования драйверов (прерывания, потоки, синхронизация очередей и т. д.); заинтересованных  читателей могу ото слать к документации, входящей в состав Windows DDK.

Сейчас мы на практике посмотрим, как можно реализовать простые драйверы устройств и, чтобы почувствовать, как это работает, создадим простейший драйвер.

Источник:  Магда Ю. С. Компьютер  в домашней лаборатории.  – М.: ДМК Пресс, 2008. – 200 с.: ил.

Оставить комментарий

микросхемы мощности Устройство импульсов питания пример приемника провода витков генератора выходе напряжение напряжения нагрузки радоэлектроника работы сигнал сигнала сигналов управления сопротивление усилитель усилителя усиления устройства схема теория транзистора транзисторов частоты