скачать рефераты
  RSS    

Меню

Быстрый поиск

скачать рефераты

скачать рефератыКурсовая работа: Протоколирование обмена информацией между компьютером и внешним запоминающим USB-устройством

Следует отметить, что функции работы с файлами могут работать только на уровне IRQL, равном PASSIVE_LEVEL. Это приводит к необходимости применения специальной методики при протоколировании обмена данными с USB‑накопителем.

1.9 Работа с реестром в режиме ядра

Работа с реестром из драйвера уровня ядра необходима, так как именно в системном реестре хранится информация о настройках протоколирования. Информация о настройках хранится в ключе реестра, связанном с устройством, к которому подключается драйвер-фильтр. Имя этого устройства соответствует шаблону HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\XXX\XXX\DeviceParameters.

Доступ ключу устройства в реестре в драйвере предоставляется функцией IoOpenDeviceRegistryKey. Перечислим ее параметры:

Таблица 1.9.1. Параметры функции IoOpenDeviceRegistry

Тип параметра

Описание параметра

IN PDEVICE_OBJECT DeviceObject Указатель на объект физического устройства, ключ которого должен быть открыт
IN ULONG DevInstKeyType Параметр определяющий, связан ли открываемый ключ непосредственно с физ. устройством или его программным обеспечением
IN ACCESS_MASK DesiredAccess Этот параметр определяет права доступа к ключу
OUT PHANDLE DevInstRegKey Указатель на переменную, куда следует поместить дескриптор открытого ключа

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


Таблица 1.9.2. Параметры функции ZwOpenKey

Тип параметра

Описание параметра

OUT PHANDLE KeyHandle Указатель на переменную, куда следует поместить дескриптор открытого ключа
IN ACCESS_MASK DesiredAccess Этот параметр определяет права доступа к ключу
IN POBJECT_ATTRIBUTES pObjectAttributes Указатель на заполненную вызывающим кодом структуру данных, которая при использовании в данной функции должна содержать имя открываемого ключа

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

Таблица 1.9.3. Параметры функции ZwQueryValueKey

Тип параметра

Описание параметра

IN HANDLE KeyHandle Дескриптор ключа, которому принадлежит считываемый параметр
IN PUNICODE_STRING ValueName Строка юникод-символов, содержащая имя параметра ключа

IN KEY_VALUE_INFORMATION_CLASS

KeyValueInformationClass

Этот параметр принимает одно их трех значений в зависимости от полноты информации о параметре:

KeyValueBasicInformation

KeyValueFullInformation

KeyValuePartialInformation

OUT PVOID KeyInformation Указатель на буфер, выделенный вызывающим кодом, в который должна быть помещена запрашиваемая информация
IN ULONG Length Длина предоставленного буфера
OUT PULONG ResultLength Указатель на переменную, содержащую число реально записанных в KeyInformation байт

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


1.10 MDL‑списки

MDL‑список – это структура, хранящая отображение блока виртуальной памяти на физическую память. MDL‑список используется в разрабатываемом драйвере для хранения информации из URB‑пакетов, связанных с вводом / выводом USB‑устройства. Кроме того, обмен информацией с USB‑устройством в режиме прямого доступа к памяти ведется именно посредством MDL‑списков.

Перед использовании MDL‑списка в драйвере необходимо провести ряд подготовительных действий:

·     выделить область в страничной памяти с помощью вызова функции
ExAllocatePool;

·     вызвать функцию MmCreateMdl, создающую и инициализирующую MDL‑список;

·     выполнить фиксацию страниц, описанных в MDL‑списке, в физической памяти с помощью вызова функции MmProbeAndLockPages.

После завершения использования MDL‑списка его следует освободить:

·     отменить фиксацию страниц страничной памяти в оперативной памяти вызовом функции MmUnlockPages;

·     очистить MDL‑список, вызвав функцию IoFreeMdl;

·     освободить выделенную под список страничную память вызовом
 ExFreePool.


2. Конструкторский раздел

2.1 Точки входа разрабатываемого драйвера

Разрабатываемый драйвер является драйвером нижнего уровня. В стеке драйверов USB‑накопителя он находится непосредственно под драйвером устройства, если после его загрузки не произойдет установки какого-либо другого драйвера-фильтра нижнего уровня.

Разрабатываемый драйвер включает в себя следующие точки входа:

·     DriverEntry;

·     AddDevice;

·     DriverUnload;

·     Функции обработки IRP‑пакетов:

·     обработка IRP‑пакетов с кодами IRP_MJ_INTERNAL_DEVICE_CONTROL – функция DispatchInternalDeviceControl;

·     обработка IRP пакетов с прочими кодами – функция DispatchRoutine.

Рассмотрим каждую из них более подробно.

2.1.1 Функция DriverEntry

В этой функции происходит регистрация всех стандартных точек входа драйвера и обработчиков IRP‑пакетов. В разрабатываемом драйвере пакеты IRP c кодами, не равными IRP_MJ_INTERNAL_DEVICE_CONTROL обрабатываются функцией DispatchRoutine.

2.1.2 Функция AddDevice

Управление этой функции передается диспетчером ввода / вывода после того, как завершает свою работу DriverEntry. AddDevice создает функциональный объект устройства с помощью вызова IoCreateDevice и подключает его к стеку драйверов выбранного устройства (вызовом IoAttachDeviceToDeviceStack). Кроме того, в этой функции производятся действия по подготовке к протоколированию: считываются настройки из системного реестра, выделяется буфер для сбора протоколируемой информации, создается лог-файл.

2.1.3 Функция DriverUnload

Функция DriverUnload необходима для того, чтобы сделать драйвер выгружаемым. В унаследованных драйверах на эту функцию возложен весь процесс выгрузки драйвера: удаление символьных ссылок, объектов устройств драйвера, отключение прерываний от объектов, освобождение выделенной памяти. В WDM‑драйверах все эти действия возложены на функцию-обработчик пакетов с кодом IRP_MJ_PNP.

2.1.4 Функция DispatchRoutine

На эту функцию возложены обязанности по обработке IRP‑пакетов с различными кодами, хотя в разрабатываемом драйвере существует необходимость в обработке только двух типов запросов. Все запросы с кодом, отличным от IRP_MJ_PNP передаются по стеку драйверов без изменений. Запросы же IRP_MJ_PNP диспетчеризуются по суб-кодам в функции PnP_Dispatch. Необходимость диспетчеризации по суб-кодам запросов IRP_MJ_PNP вызвана тем, что драйвер не должен нарушать порядка работы операционной системы и обязан подчиняться PnP‑менеджеру, то есть в драйвере должны корректно обрабатываться события старта и удаления устройства.

2.1.5 Функция DispatchInternalDeviceControl

Запросы ввода / вывода к USB‑накопителю передаются в составе IRP‑пакетов с кодом IRP_MN_INTERNAL_DEVICE_CONTROL. Этот пакет содержит полную информацию о направлении и характере передаваемых данных. То есть для протоколирования обмена информацией с USB‑носителем следует перехватывать пакеты именно этого типа.

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

Для сохранения протоколируемой информации используется, как уже было сказано в разделе 1.10, MDL‑список. Этот MDL‑список создается в функции AddDevice. Объем памяти, выделяемой под список, совпадает с максимальным размером лог-файла, задаваемым в пользовательском приложении. После создания список фиксируется в страничной памяти, что предотвращает его выгрузку на жесткий диск во время работы драйвера. После этих подготовительных действий список используется в функции DispatchInternalDeviceControl – он заполняется перехватываемой информацией.

Запись накопленного буфера в лог-файл происходит при удалении устройства.

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

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


2.2 Размещение кода драйвера в памяти

Некоторые функции драйвера, например те, которые выполняют инициализацию, выгодно выполнить и освободить память, занимаемую ими. В языке C есть специальная директива #pragma_alloc_text (<тип секции>, <имя размещаемой функции>), позволяющая управлять размещением кода. В качестве типа секции могут указываться значения «INIT» или «PAGE».

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

Точки входа AddDevice и DriverUnload располагаются в секции «PAGE», то есть в страничной памяти, поскольку они гарантированно вызываются на уровне привилегий, равном PASSIVE_LEVEL и, даже оказавшись выгруженными на диск, будут немедленно загружены в физическую память менеджером страничной памяти (который способен работать только на уровне PASSIVE_LEVEL).

Остальные же точки входа (DispatchRoutine и DispatchInternalDeviceControl) располагаются по умолчанию, в нестраничной памяти, поскольку их работа зависит от клиентского драйвера USB‑устройства, под которым в стеке драйверов располагается разрабатываемый драйвер-фильтр. Уровень привилегий его запросов слабо предсказуем и может быть равен DISPATCH_LEVEL. На этом уровне подкачка страниц невозможна, что при обращении к выгруженной функции приведет к краху системы.

2.3 Установка драйвера в системе

Для установки драйвера следует создать его ключ в системном реестре.
 Имя ключа должно иметь следующий вид:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\driver_name.

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

·     DisplayName – значение этого параметра описывает текст, используемый в служебных программах;

·     ErrorControl – этот параметр предписывает операционной системе способ поведения в той ситуации, когда при загрузке драйвера произошла ошибка;

·     ImagePath – описывает полный путь к файлу с исполняемым кодом драйвера;

·     Start – описывает стадию загрузки операционной системы, когда следует загружать драйвер;

·     Type – определяет тип драйвера.

Возможные значения указанных параметров можно узнать из документации MSDN.

Таким образом, первая стадия установки драйвера в систему заключается
в том, что должен быть создан ключ драйвера в реестре, а сам драйвер
скопирован в каталог, описываемый строкой ImagePath (как правило -%SystemRoot%\System32\Drivers\driver_name.sys).

Далее должно быть выбрано устройство, на которое будет установлен фильтр. Выбранному устройству в системном реестре соответствует ключ с именем вида HKLM\CurrentControlSet\Enum\USB\XXX\YYY.

Последняя часть ключа (XXX\YYY) определяется именем устройства. При установке драйвера фильтра нижнего уровня в разделе YYY создается строковый параметр LowerFilters, которому присваивается значение, совпадающее с именем драйвера, для которого был создан ключ в …\Services. Таким образом, при подключении устройства к системе для него будет создан стек драйверов, в состав которого в качестве фильтра нижнего уровня будет загружен устанавливаемый драйвер.

Кроме того, в ключе, связанном с устройством, при установке драйвера создается дополнительный раздел MyFilterParams, который хранит два параметра:

·     MaxLogSize – максимальный размер лог-файла;

·     LogFileName – имя лог-файла.


3. Технологический раздел

3.1 Выбор языка и средств программирования

Разрабатываемый программный комплекс состоит из двух частей:

·     Драйвера-фильтра;

·     Управляющего приложения для установки фильтра и ввода параметров протоколирования.

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

 

3.1.1 Драйвер-фильтр

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

·     Существует специальный компилятор C, поставляемый в составе пакета DDK, предназначенный специально для компиляции драйверов. Он содержит множество макроопределений и библиотек, позволяющих сделать процесс написания драйвера более легким. Microsoft рекомендует его как основную среду для разработки драйверов для Windows;

·     Программы на ассемблере работают быстрее, чем программы, написанные на C. Но разница в скорости между этими языками не очень велика. Зато производительность труда при использовании C намного выше, чем при использовании ассемблера.


3.1.2 Управляющее приложение

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

3.2 Структуры данных драйвера-фильтра

Для сбора информации о вводе / выводе устройства используется структура BUFFER, объявленная в драйвере следующим образом:

typedef struct _BUFFER

{

PVOID Buffer;

PMDL Mdl;

ULONG MaxSize;

ULONG CurrentSize;

} BUFFER, *PBUFFER;

Поясним значения полей структуры:

·     Buffer – указатель на буфер, хранящий информацию;

·     Mdl – указатель на MDL‑список, хранящий отображение буфера на системные страницы в памяти;

·     MaxSize – максимальный размер буфера в байтах;

·     CurrentSize – текущий размер буфера в байтах.

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

В разрабатываемом драйвере в расширении устройства расположена следующая информация:

typedef struct _DEVICE_EXTENSION

{BUFFER UrbPackets;

HANDLE LogFileHandle;

BOOLEAN PreparedToLog;

PURB Urb;

ULONG UrbCount;

PDEVICE_OBJECT topDevObject;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

Поясним назначение указанных переменных:

·     UrbPackets – буфер для протоколирования;

·     LogFileHandle – дескриптор файла, в который записывается информация о вводе / выводе;

·     PreparedToLog – флаг, указывающий на то, что подготовка к протоколированию прошла успешно;

·     Urb – пакет, информация о котором переносится в буфер UrbPackets;

·     UrbCount – число URB‑пакетов, прошедших через фильтр;

·     topDevObject – объект устройства, находящийся в стеке под нашим устройством.


3.2 Интерфейс управляющего приложения

Управляющее приложение предназначено для установки драйвера-фильтра в системе и передачи ему параметров протоколирования через системный реестр.

Интерфейс управляющего приложения состоит из главного окна, представленного на рисунке 3.2.1:

Рис. 3.2.2 Интерфейс управляющего приложения

В левой части окна расположен список, в котором отображаются имена устройств, присутствующих в системе.

Перед установкой драйвера-фильтра на некоторый USB‑накопитель, следует создать ключ драйвера в системном реестре. Для этого следует разместить файл драйвера MyUSBFlt.sys в корневом каталоге управляющего приложения и нажать кнопку «Создать ключ драйвера». По окончании операции будет выдано сообщение о ее результате.

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

Драйвер-фильтр начнет свою работу после того, как устройство, на которое он был установлен, будет перезапущено. Перезапуск можно осуществить путем выделения нужного устройства в списке и нажатия кнопки «Перезапустить устройство». Того же результата можно добиться, перезапустив устройство типа «Хост-контроллер» или «Корневой концентратор», к которому подключен рассматриваемый USB‑накопитель. Возможен также перезапуск устройства путем отсоединения от порта концентратора и последующего подключения к нему.

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

3.3 Тестирование драйвера-фильтра

Драйвер был протестирован с использованием стандартной тестирующей утилиты DriverVerifier, поставляемой в составе пакета DDK. С помощью этой утилиты были проведены следующие тесты:

·     Операции с пулами памяти;

·     Корректность уровней IRQL, на которых выполняется код драйвера;

·     Нехватка ресурсов;

·     Нетипичные запросы к драйверу.

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

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


Заключение

В данной работе рассмотрен вопрос, связанный с разработкой драйверов устройств в системе Windows, и реализован драйвер-фильтр USB‑накопителя.

Разработанный драйвер предоставляет следующие возможности:

·     возможность установки на любой USB‑накопитель, присутствующий в системе;

·     перехват информации ввода / вывода USB‑накопителя;

·     запись перехваченной информации в файл на диске.

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

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


Список литературы и интернет-ресурсов

1. Агуров П.В. Интерфейсы USB. Практика использования и программирования. – СПб.: БХВ-Петербург, 2004. – 576 с.

2. Солдатов В.П. Программирование драйверов Windows. Изд. 2-е, перераб. и доп. – М.: ООО «Бином-Пресс», 2004. – 480 с.

3. Материалы проекта «Windows Assembly Site» – www.wasm.ru.

4. Материалы сайта www.usb.org.

5. MSDN Library, Copyright 1987–2005 Microsoft Corporation.


Страницы: 1, 2, 3, 4


Новости

Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

  скачать рефераты              скачать рефераты

Новости

скачать рефераты

Обратная связь

Поиск
Обратная связь
Реклама и размещение статей на сайте
© 2010.