Использование NuMega DriverStudio для написания WDM-драйверов
Шрифт:
И драйвер, и приложение пользователя различают, какую функцию управления устройством вызвать, при помощи IOCTL-кодов. Такой код представляет собой обыкновенное 32-разрядное число. Для удобства ему директивой #define задают какое-то понятное имя. Например, в нашем случае зададим IOCTL-код, при получении которого драйвер будет возвращать количество памяти "на борту" PCI-устройства.
Если при чтении драйверу посылается IRP-пакет со старшим кодом функции IRP_MJ_READ, при записи — IRP_MJ_WRITE, то при вызове функции DeviceIOControl для нашего устройства драйвер получает пакет со старшим кодом IRP_MJ_IOCONTROL и младшим — код самой IOCTL-функции. Метод DeviceControl вызывается при получении драйвером IRP со старшим кодом IRP_MJ_DEVICE_CONTROL. Она действует подобно методу StartIo. В зависимости от кода IOCTL производится вызов соответствующей функции.
Метод XDSPDRV_IOCTL_GETMEMSIZE_Handler является обработчиком IOCTL–кода XDSPDRV_IOCTL_GETMEMSIZE. Получив этот код, драйвер возвращает общий объем памяти устройтсва. Шаблон метода сгенерирован DriverWizard, но программист должен написать практически весь его код.
Написание драйвера завершено. Возможно, у Вас сложилось впечатление, что DriverWizard может практически все и написание драйвера — очень простая задача. Но не следует забывать, что наш драйвер — всего-то простейшая демонстрационная программа, которая практически не выполняет никаких полезных действий. Написание реальных драйверов является гораздо более сложной задачей.
Если бы драйвер был написан с использованием пакета DDK, то он бы имел практически ту же структуру и почти тот же код (правда, не объектно-ориентированный). Но в таком случае весь драйвер пришлось бы писать вручную, а DriverWizard генерирует скелет драйвера автоматически. Это сильно облегчает процесс разработки драйвера, позволяя программисту не заботиться о написании скелета драйвера и предохраняя его от возможных ошибок.
2.4 Разработка dll-библиотеки для взаимодействия с драйвером
dll-библиотека (Dynamic Link Library) — программный модуль, который может быть динамически подключен к выполняющемуся процессу. Dll–библиотека может содержать функции и данные. При подключении dll к процессу она отображается на адресное пространство этого процесса.
Если говорить по русски, то это означает: в любой момент времени программа может загрузить dll-библиотеку, получить указатели на функции и данные этой библиотеки. Потом приложение как-то использует функции и данные библиотеки, и когда они больше не нужны — выгружает библиотеку.
Dll-библиотека содержит два вида функций: внешние (External) и внутренние (Internal). Внутренние функции могут вызываться только самой dll, а внешние может также вызывать приложение, подключившее библиотеку. В этом случае говорят, что dll-библиотека экспортирует функции и данные.
Как было упомянуть выше, в настоящее время для связи с драйвером используется схема Приложение→Библиотека dll→Драйвер. При использовании такой архитектуры запрос приложения на операцию ввода-вывода поступает в dll-библиотеку, проходит там предварительную обработку и передается драйверу. Результат, возвращенный драйвером библиотеке dll, также обрабатывается и передается приложению. Преимущества такого подхода очевидны:
• Выпускается огромное количество различных периферийных устройств, и, соответственно, для каждого устройства разрабатывается свой драйвер. Программисту будет тяжело разбираться во всех тонкостях работы драйвера устройства: формат данных для чтения/записи, запоминать непонятные IOCTL-коды. Гораздо лучше — предоставить для него понятный интерфейс API-функций для работы с устройством. Еще лучше, если такой интерфейс будет унифицированным для всех устройств данного типа. Задача dll-библиотеки, поставляемой с драйвером – связать стандартные интерфейсы, предоставляемые прикладной программе, со специфическими алгоритмами работы драйвера.
• если в будущем измениться алгоритм взаимодействия приложения с драйвером, то пользователю для работы с новым драйвером будет необходимо обновить только библиотеку dll. Все ранее разработанные программы остануться прежними.
Естественно, такой подход имеет свои минусы. В данном случае за счет большего числа вызовов, через которые проходит запрос на ввод-вывод, снижается быстродействие работы системы.
В нашем случае нам необходимо разработать dll-библиотеку, которая будет предоставлять приложению три функции: чтение памяти, запись в память и получение общего количества памяти устройства. Естественно, dll – библиотеку мы также будем проектировать в среде Visual C++.