Смекни!
smekni.com

Разработка драйвера виртуального жесткого диска (стр. 5 из 5)

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_GET_PARTITION_INFO \n" ) );

if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <sizeof(PARTITION_INFORMATION))

{

DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("Output buffer too small... &bsol;n" ) );

status = STATUS_BUFFER_TOO_SMALL; // Нужен буфер больше

information = sizeof(PARTITION_INFORMATION);

}

else

{

PPARTITION_INFORMATION outputBuffer;

outputBuffer = ( PPARTITION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;

outputBuffer->PartitionType = (UCHAR)devExt->DiskRegInfo.PartitionType;

outputBuffer->BootIndicator = FALSE;

outputBuffer->RecognizedPartition = FALSE

outputBuffer->RewritePartition = FALSE;

outputBuffer->StartingOffset = RtlConvertUlongToLargeInteger(0);

outputBuffer->PartitionLength = RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize);

outputBuffer->HiddenSectors = (ULONG) (1L);

outputBuffer->PartitionNumber = (ULONG) (1L);

status = STATUS_SUCCESS;

information = sizeof( PARTITION_INFORMATION );

}

break;

}

Запросы IOCTL_DISK_GET_MEDIA_TYPES, IOCTL_DISK_GET_DRIVE _GEOMETRY нужны для поучения информации о геометрии диска, для этого надо заполнить структуру DISK_GEOMETRY описанную в разделе 2.7.:


typedef struct _DISK_GEOMETRY {

LARGE_INTEGER ; //количество цилиндров

MEDIA_TYPE ; //тип носителя

ULONG ; //количество дорожек на цилиндр

ULONG ; //количество секторов на дорожку

ULONG ; //размер сектора в байтах

} DISK_GEOMETRY, *PDISK_GEOMETRY;

Все остальные параметры заранее рассчитаны и определены при инициализации, и нужно только эту структуру скопировать из расширения устройства:

PDISK_GEOMETRY outputBuffer;

outputBuffer = ( PDISK_GEOMETRY ) Irp->AssociatedIrp.SystemBuffer;

RtlCopyMemory( outputBuffer, &(devExt->DiskGeometry), sizeof(DISK_GEOMETRY) );

status = STATUS_SUCCESS;

DBGPRINT(DBG_COMP_IOCTL,DBG_LEVEL_INFO,("IOCTL_DISK_GET_DRIVE_GEOMETRY-OK!&bsol;n"));

information = sizeof( DISK_GEOMETRY );

3.4.4 Обработка запросов Plug and Play

При запуске устройства мы получаем IRP пакет с кодом IRP_MN_START_DEVICE:


case IRP_MN_START_DEVICE:

{

KeInitializeEvent( &event, NotificationEvent, FALSE);

IoCopyCurrentIrpStackLocationToNext( Irp );

IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE) RamDskIoCompletionRoutine,

(PVOID) &event, TRUE, TRUE, TRUE );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

if (status == STATUS_PENDING)

{

KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );

}

if ( NT_SUCCESS(status) )

{

// успешно запущен нижний драйвер

devExt->DevState = WORKING;

}

COMPLETE_REQUEST( Irp, status, 0 );

break;

}

Мы пересылаем пакет драйверу, который находится ниже при помощи вызова функции IoCallDriver. Если нижние драйвер находится в состоянии обработки (STATUS_PENDING), то просто усыплем наш драйвер с помощью функции KeWaitForSingleObject и просыпаемся по событию завершения операции нижним драйвером.

При остановке устройства(IRP_MN_STOP_DEVICE), просто пересылаем запрос нижнему драйверу и устанавливаем состояние устройства STOPPED:


case IRP_MN_STOP_DEVICE:

{

devExt->DevState = STOPPED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

При обработке запросов IRP_MN_SURPRISE_REMOVAL, IRP_MN_QUERY_ REMOVE_DEVICE, IRP_MN_QUERY_STOP_DEVICE, производятся аналогичные действия, с установкой соответствующего статуса:

case IRP_MN_QUERY_STOP_DEVICE:

{

devExt->DevState = PENDINGSTOP;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_STOP_DEVICE:

{

devExt->DevState = STOPPED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_QUERY_REMOVE_DEVICE:

{

devExt->DevState = PENDINGREMOVE;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

case IRP_MN_SURPRISE_REMOVAL:

{

devExt->DevState = SURPRISEREMOVED;

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

break;

}

При удалении устройства IRP_MN_REMOVE_DEVICE, мы вызываем функцию RamDskRemoveDevice, которая освобождает выделенную при инициализации память, символическую ссылку (она будет описана далее):

case IRP_MN_REMOVE_DEVICE:

{

RamDskRemoveDevice( DeviceObject, Irp );

lockHeld = FALSE;

break;

}

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

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

При удалении объекта устройства, менеджер ввода вывода посылает IRP пакет IRP_MN_REMOVE_DEVICE, тогда вызывается процедура RamDskRemove Device. IRP пакет передаем дальше драйверу нижнего уровня с помощью функции IoCallDriver. Статус драйвера устанавливается в состояние устройство удалено, чтобы новые запросы не могли быть выполнены. С помощью функции IoReleaseRemoveLockAndWait ждем пока текущие запросы не обработаются.

Irp->IoStatus.Status = STATUS_SUCCESS;

IoSkipCurrentIrpStackLocation( Irp );

status = IoCallDriver( devExt->LowerDeviceObject, Irp );

devExt->DevState = REMOVED;

IoReleaseRemoveLockAndWait(&devExt->RemoveLock, Irp);

driverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject,

RAMDSK_DRIVER_EXTENSION_KEY);

ASSERT ( driverExtension != NULL );

driverExtension->DeviceInitialized = FALSE;

RamDskCleanUp( DeviceObject );

Перед удалением расширения объекта устройства в процедуре RamDskCleanUp освобождается память под образ диска, удаляется символическая ссылка и сам функциональный объект устройства. Также далее сбрасывается признак DeviceInitialized инициализации устройства.

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


VOID RamDskUnload(IN PDRIVER_OBJECT DriverObject)

{

PRAMDSK_DRIVER_EXTENSION driverExtension;

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("Driver Unload&bsol;n") );

ASSERT(DriverObject->DeviceObject == NULL);

driverExtension = IoGetDriverObjectExtension(DriverObject,RAMDSK_DRIVER_EXTENSION_KEY);

ASSERT ( driverExtension != NULL );

if ( driverExtension->RegistryPath.Buffer )

{

ExFreePool( driverExtension->RegistryPath.Buffer );

}

return;

} // Конец RamDskUnload()

В данной процедуре удаляется уже расширение драйвера.

3.5 Программа настройки параметров виртуального диска

Чтобы предоставить пользователю возможность настроить параметры виртуального диска разработана программа RamDskConfig.exe. Общий вид программы изображен на рис. 4

Рис. 4 Программа настройки параметров виртуального диска

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

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

Для сохранения изменений, пользователю требуется нажать кнопку «ОК». При этом происходит рестарт драйвера с новыми параметрами. Чтобы не сохранять изменения, нужно нажать кнопку «Отмена».

3.6 Установка драйвера

Установка драйвера производится с использованием установочного файла RAMDsk.inf, поставляемого вместе с драйвером. Для установки фильтра необходимо выполнить следующие действия:

1. Откройте окно Мастера оборудования (например, из вкладки Оборудование окна Свойства системы).

2. Выберите пункт Добавить/провести диагностику устройства

3. В появившемся списке устройств выберите Добавление нового устройства

4. Далее укажите Нет, выбрать оборудование из списка

5. Укажите тип устройства Другие устройства

6. Нажмите на кнопку Установить с диска и вставьте дискету с файлами драйвера-фильтра в дисковод.

7. После этого в появившемся окне выберите путь к дискете и нажмите ОК.

8. Нажмите кнопку Далее для начала установки.

9. Если в ходе установки система выдаст предупреждение о том, что устанавливаемый драйвер не имеет цифровой подписи, нажмите кнопку Все равно продолжить.

10. После установки нажмите кнопку Готово для закрытия мастера установки

11. При необходимости настройки драйвера скопируйте файл RamDskConfig.exe на диск.


4. ЭКСПЕРИМЕНТАЛЬНО-ИССЛЕДОВАТЕЛЬСКИЙ РАЗДЕЛ

4.1 Описание экспериментов

Для исследования временных характеристик использовалась программа HD TACH 2.70, исследовались следующие характеристики:

· скорость последовательного чтения

· время доступа при случайном обращении

· загрузка процессора при операциях записи/чтения

Эксперименты проводились на компьютере Intel Pentium III 566 МГц, 196 Мб ОП, Windows 2000 Server, размер рамдиска 32 Мбайта.

4.2 Результаты экспериментов

В таблице 4 показаны результаты тестирования для рамдиска, для сравнения приведены результаты для жесткого диска Segate Barracuda 4 7200

Таблица 4 Результаты тестирования

Характеристика Рамдиск Жесткий диск
Скорость последовательного чтения Мб/с 189,5 40,0
Время доступа при случайном обращении, мс 0,0 15,2
Загрузка ЦП 100% 10%

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

Скорость передачи данных для рамдиска также ограничивается скоростью обмена данными в памяти (для данной платформы обмен данными с оперативной памятью равен 250 Мб/с).

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


ЗАКЛЮЧЕНИЕ

В данной работе были исследованы вопросы, связанные с разработкой драйверов для устройств хранения, способами хранения данных, управление работой устройства с помощью команд PnP. Разработан классовый драйвер виртуального диска, который полностью удовлетворяет всем указанным требованиям.

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

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

Параметры диска изменяются динамически и без необходимости перезагрузки системы.

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


СПИСОК ИСПОЛЬЗОВАННОЙ ЛИТЕРАТУРЫ

1. Oney W. Programming the Microsoft Windows Driver Model. — Redmond, Washington: Microsoft Press., 1999.

2. В.Г.Олифер, Н.А.Олифер Сетевые операционные системы. Учебник для ВУЗов – СПб.: Издательство «ПИТЕР», 2004 – 544 с.: ил.

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

4. Microsoft Windows XP DDK Documentation.