48554 (Разработка драйвера виртуального жесткого диска), страница 3

2016-07-30СтудИзба

Описание файла

Документ из архива "Разработка драйвера виртуального жесткого диска", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "курсовые/домашние работы", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "48554"

Текст 3 страницы из документа "48554"

где DiskSize – размер диска.

Если количество цилиндров превышает 1023(такое ограничение было введено для совместимости со старыми версиями BIOS), то количество секторов на дорожку увеличивается вдвое и будет равно 64.

Таким образом максимальный размер рамдиска, для которого число цилиндров не превышает 1023 равен:

MaxDiskSize = 1023*16*64*512 = 536346624 байт= 511.5 Мбайт,

что более чем достаточно для нашей версии рамдиска.

2.7 Структура драйвера

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

  • Инициализация драйвера

  • Обработка запросов PnP и управления питанием

  • Обработка запросов записи/чтения данных

  • Обработка расширенных запросов

  • Выгрузка драйвера

3. ТЕХНОЛОГИЧЕСКИЙ РАЗДЕЛ


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

Для разработки драйвера виртуального диска применялся пакет DDK (Driver Development Kit), который включает в себя все необходимые заголовочные файлы и библиотеки. Пакет DDK ориентирован на язык С. Драйвер разрабатывался на Windows 2003 Server DDK, т.к. она включает в себя как средства для разработки драйверов для Windows 2003 Server, так и последние версии средств для разработки драйверов ОС Windows 2000 и XP.

В качестве интегрированной среды разработки применялся Microsoft Visual C++ 6. Он предоставляет удобный интерфейс для написания программного кода на C, и позволяет компилировать его используя библиотеки пакета DDK.

Для отладки работы драйвера применялись программы DebugView и DriverMonitor из пакета NuMega Driver Studio 2.0, которые позволяют просматривать отладочные сообщения драйвера.


3.2 Структуры данных классового драйвера

Параметры диска и его состояние хранятся в расширении устройства — структуре DEVICE_EXTENSION. Она всегда доступная через объект-устройство (DEVICE_OBJECT, поле DeviceExtension), она реализует наиболее удобный и рекомендованный Microsoft способ хранения таких данных. Структуру расширения определяет разработчик драйвера. Мы ее определим так:

typedef struct _DEVICE_EXTENSION

{

PDEVICE_OBJECT DeviceObject;

PDEVICE_OBJECT LowerDeviceObject;

DEVICE_STATE DevState; // Текущее состояние устройство

IO_REMOVE_LOCK RemoveLock; // Блокировка устройства

ULONG Flags; // Флаг устройства

PUCHAR DiskImage; // Указатель на образ диска

DISK_GEOMETRY DiskGeometry; // Параметры геометрии диска

DISK_INFO DiskRegInfo; // Параметры диска из реестра

UNICODE_STRING SymbolicLink; // Символическая ссылка

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

Поля DeviceObject и LowerDeviceObject облегчают доступ к объектам-устройствам из различных участков драйвера. Они потребуются в дальнейшем. Поле RemoveLock служит для блокировки удаления устройства. DiskImage – содержит указатель на одномерный массив – образ диска. Поле DiskGeometry хранит геометрию диска. DevState содержит текущее состояние устройства. SymbolicLink – символическая ссылка, которая служит для обращения к драйверу.

Поле DiskRegInfo описывает параметры, которые расположены в реестре и используются драйвером для создания диска:

typedef struct _DISK_INFO

{

ULONG DiskSize; // Размер диска в байтах

ULONG RootDirEntries; // Количество элементов в корне

ULONG SectorsPerCluster; // Секторов на кластер

UNICODE_STRING DriveLetter; // Буква диска

} DISK_INFO, *PDISK_INFO;


3.3 Блокировка выгрузки устройства

Когда система производит удаление нижестоящего устройства, она посылает ему PnP-запрос с функцией IRP_MN_REMOVE_DEVICE. Если же в этот момент драйвер чем-то занят, то он должен защитить своё устройство от преждевременной выгрузки из памяти. Для этого в системе предусмотрен объект «блокировка выгрузки» (remove lock). Он может быть «захвачен» и «освобождён». Внутри этого объекта имеется счётчик. Этот счётчик устанавливается в ноль при инициализации объекта (функция IoInitializeRemoveLock). Счётчик увеличивается на единицу при захвате объекта (IoAcquireRemoveLock) перед обработкой запроса и уменьшается при освобождении (IoReleaseRemoveLock).

Обработчик PnP-запроса с функцией IRP_MN_REMOVE_DEVICE гарантированно исполняется в контексте системного процесса. В этом обработчике перед удалением объекта-устройства над блокировкой выполняется действие «освободить и ждать» (IoReleaseRemoveLockAndWait). Оно уменьшает счётчик на единицу и блокирует системный процесс, пока счётчик не станет равным нулю. Следовательно, пока драйвер обрабатывает хотя бы один запрос к устройству, это устройство не будет удалено.


3.4 Процедуры драйвера виртуального диска


3.4.1 Инициализация драйвера

Начнём с процедуры, вызываемой при инициализации драйвера — DriverEntry. Она определяется следующим образом:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)

Тип NTSATUS, соответствующий возвращаемому значению, определяет тип ошибки. Многие функции драйвера возвращают значение этого типа. Если работа проходит успешно, результат принимает значение STATUS_SUCCESS.

В данной процедуре необходимо сообщить системе остальные процедуры обработки пакетов IRP:

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

DriverObject->MajorFunction[IRP_MJ_CREATE] = RamDskCreateClose; DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamDskCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = RamDskReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE] = RamDskReadWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamDskIOCtl; DriverObject->MajorFunction[IRP_MJ_PNP] = RamDskDispatchPnp; DriverObject->MajorFunction[IRP_MJ_POWER] = RamDskDispatchPower; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamDskDispatchSystemControl; DriverObject->DriverExtension->AddDevice = RamDskAddDevice; DriverObject->DriverUnload = RamDskUnload;

Массив MajorFunction устанавливает соответствие между кодом типа запроса IRP_MJ_NNN и диспетчерской функцией, которая его обрабатывает. Наш драйвер обрабатывает запросы на открытие и закрытие устройства (RamDskCreateClose), чтение и запись (RamDskReadWrite), расширенные запросы обработки IOCTL(RamDskIOCtl), запросы Plug and Play (RamDskDispatchPnp), функции управления питанием (RamDskDispatchPower), запросы от подсистемы инструментария Windows (RamDskDispatchSystemControl).

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

typedef struct _RAMDSK_DRIVER_EXTENSION { UNICODE_STRING RegistryPath; ULONG DeviceInitialized; } RAMDSK_DRIVER_EXTENSION, *PRAMDSK_DRIVER_EXTENSION;

В процедуре DriverEntry мы создаем экземпляр структуры и инициализируем ее поля: копируем путь реестра RegistryPath, который передается в параметрах процедуры, и сбрасываем признак DeviceInitialized того, что устройство добавлено.

status = IoAllocateDriverObjectExtension(DriverObject, RAMDSK_DRIVER_EXTENSION_KEY, sizeof(RAMDSK_DRIVER_EXTENSION), &driverExtension); // Сохраним путь реестра driverExtension->RegistryPath.Length = RegistryPath->Length; driverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength + sizeof(UNICODE_NULL); driverExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, driverExtension->RegistryPath.MaximumLength, RAMDSK_TAG_GENERAL); RtlCopyUnicodeString( &(driverExtension->RegistryPath), RegistryPath); driverExtension->DeviceInitialized = FALSE;

Процедура RamDskAddDevice будет вызвана, когда будет обнаружено устройство. Ее действие заключается в создании объекта устройства диска и создании символических ссылок для него.

Проверим, может быть уже создан объект устройство, а процедура RamDskAddDevice вызывается повторно. Для этого проанализируем признак DeviceInitialized расширения драйвера:

// Может присутствоать только одно устройство, если повторно вызывается запрос

// AddDevice для следующего устройства, отклоним запрос

if ( driverExtension->DeviceInitialized == TRUE )

{

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_ERROR, ("Device exists\n") );

return STATUS_DEVICE_ALREADY_ATTACHED;

}

Если процедура RamDskAddDevice вызвана в первый раз, создаем объект устройство с типом дисковый накопитель (FILE_DEVICE_DISK) и инициализируем расширение устройства DEVICE_EXTENSION:

status = IoCreateDevice(

DriverObject,

sizeof(DEVICE_EXTENSION),

&uniDeviceName,

FILE_DEVICE_DISK ,

(FILE_DEVICE_SECURE_OPEN),

FALSE,

&functionDeviceObject);

Если создание прошло успешно, мы читаем параметры диска из реестра и устанавливаем начальное состояние устройства остановлено (STOPPED) в расширении устройства, а также устанавливаем флаги сигнализирующие о том, что мы используем прямой метод передачи данных (DO_DIRECT_IO) и процедуры драйвера находятся в страничной памяти(DO_POWER_PAGABLE):

RamDskQueryDiskRegParameters(&driverExtension->RegistryPath,&devExt->DiskRegInfo);

devExt->DevState = STOPPED; // состояние остановлен

// Установим флаги

functionDeviceObject->Flags |= DO_POWER_PAGABLE;

functionDeviceObject->Flags |= DO_DIRECT_IO;

// Резервируем память под образ диска

devExt->DiskImage =

ExAllocatePoolWithTag ( NonPagedPool,

devExt->DiskRegInfo.DiskSize,

RAMDSK_TAG_DISK ) ;

Последней операцией мы резервируем память в нестраничном пуле под образ диска(размер образа devExt->DiskRegInfo.DiskSize байт).

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

RamDskFormatDisk( functionDeviceObject );

Создаем символическую ссылку, которая ассоциирует с нашим драйвером указанную в параметрах букву диска и имеет формат «\DosDevices\X:», где «Х» - буква диска.

RtlInitUnicodeString( &uniWin32Name, DOS_DEVICE_NAME );

devExt->SymbolicLink.MaximumLength = DOS_DEVNAME_LENGTH;

devExt->SymbolicLink.Length = uniWin32Name.Length;

RtlCopyUnicodeString( &(devExt->SymbolicLink), &uniWin32Name );

RtlAppendUnicodeStringToString(&(devExt->SymbolicLink),&(devExt->DiskRegInfo.DriveLetter));

// Создаем символьную ссылку в пространстве имен Win32

status = IoCreateSymbolicLink( &devExt->SymbolicLink, &uniDeviceName );

Если символическая ссылка создана без ошибок, то установим в расширении устройства флаг, что символическая ссылка создана и устройство подключается к стеку устройств:. При выгрузке драйвера если флаг установлен будет удаляться и символическая ссылка драйвера:

devExt->Flags |= FLAG_LINK_CREATED;

devExt->LowerDeviceObject = // подключение к стеку устройств

IoAttachDeviceToDeviceStack( functionDeviceObject, PhysicalDeviceObject );

// Сбросим флаг DO_DEVICE_INITIALIZING

functionDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

// устройство добавлено успешно

driverExtension->DeviceInitialized = TRUE;

Последней операцией устанавливается признак DeviceInitialized расширения драйвера, что устройство добавлено.


3.4.2 Обработка запросов записи/чтения

Когда пользовательское приложение или компонент ядра пытается открыть драйвер виртуального диска для записи или чтения, то диспетчер ввода вывода формирует запросы IRP с кодом IRP_MJ_CREATE. При закрытии обрабатывается запрос IRP_MJ_CLOSE. Особых действий в обработке этих пакетов не требуется, поэтому драйвер возвращает успешный статус завершения. В данном драйвере оба пакета обрабатываются в одной процедуре RamDskCreateClose:

switch ( irpStack->MajorFunction )

{

case IRP_MJ_CREATE:

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Нет! Мы не выполняем работы на заказ, однако Вы можете попросить что-то выложить в наших социальных сетях.
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
4098
Авторов
на СтудИзбе
667
Средний доход
с одного платного файла
Обучение Подробнее