на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Драйвер виртуального диска
p align="left">switch ( irpStack->MajorFunction )

{case IRP_MJ_CREATE:

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CREATE (%p)\n", Irp) );

COMPLETE_REQUEST( Irp, status, 0 );

break;

case IRP_MJ_CLOSE:

DBGPRINT( DBG_COMP_INIT, DBG_LEVEL_INFO, ("IRP_MJ_CLOSE (%p)\n", Irp) );

COMPLETE_REQUEST( Irp, status, 0 );

break;

default:

status = STATUS_NOT_IMPLEMENTED;

COMPLETE_REQUEST( Irp, status, 0 );

ASSERTMSG("BUG: we should never get here", 0);

break;

} // switch

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

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

if ( devExt->DevState != WORKING )

{// Устройство не готово или удалено, отменить любые запросы

DBGPRINT( DBG_COMP_READ, DBG_LEVEL_WARN, ("Device not ready\n" ) );

status = STATUS_INVALID_DEVICE_STATE;

COMPLETE_REQUEST( Irp, status, information );}

Далее требуется проверить, что переданные параметры(начальное смещение Parameters.Read.ByteOffset и количество байт Parameters.Read.Length) не выходят за границы нашего диска, чтобы обеспечить корректность операции чтения/записи. Дополнительно количество байт должно быть кратно размеру сектора на диске:

if (RtlLargeIntegerGreaterThan(

RtlLargeIntegerAdd(

irpStack->Parameters.Read.ByteOffset,

RtlConvertUlongToLargeInteger(irpStack->Parameters.Read.Length)),

RtlConvertUlongToLargeInteger(devExt->DiskRegInfo.DiskSize)) ||

(irpStack->Parameters.Read.Length & (devExt->DiskGeometry.BytesPerSector - 1)))

{DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR,

("Error invalid parameter\n"

"ByteOffset: %x\n"

"Length: %d\n"

"Operation: %x\n",

irpStack->Parameters.Read.ByteOffset,

irpStack->Parameters.Read.Length,

irpStack->MajorFunction));

status = STATUS_INVALID_PARAMETER;

COMPLETE_REQUEST( Irp, status, information );

IoReleaseRemoveLock(&devExt->RemoveLock, Irp);

return status;}

Если какой-либо из параметров не верен, то статус обработки запроса будет равен STATUS_INVALID_PARAMETER (неверные параметры).

Драйвер использует прямой метод передачи буфера данных, нам передается MDL список для буфера пользователя в параметре Irp->MdlAddress, который мы отображаем в адресное пространство ядра с помощью функции MmGetSystemAddressForMdlSafe:

ASSERT ( Irp->MdlAddress != NULL );

currentAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);

if ( currentAddress == NULL )

{status = STATUS_INSUFFICIENT_RESOURCES;

COMPLETE_REQUEST( Irp, status, information );

IoReleaseRemoveLock(&devExt->RemoveLock, Irp);

DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR, ("Unable to get the system-space virtual address\n" ) );

return status;}

Когда адрес получен адрес буфера (currentAddress), можно произвести копирование данных с помощью функции RtlMoveMemory

information = irpStack->Parameters.Read.Length;

switch (irpStack->MajorFunction)

{case IRP_MJ_READ:

RtlMoveMemory(

currentAddress,

devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,

irpStack->Parameters.Read.Length);

break;

case IRP_MJ_WRITE:

RtlMoveMemory(

devExt->DiskImage + irpStack->Parameters.Read.ByteOffset.LowPart,

currentAddress, irpStack->Parameters.Read.Length);

break;

default:

information = 0;

break;}

status = STATUS_SUCCESS;

COMPLETE_REQUEST( Irp, status, information );

При этом поле information содержит количество байт, которые были записаны/прочитаны.

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

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

case IOCTL_DISK_IS_WRITABLE://проверка можно ли на диск записывать данные

{DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_IS_WRITABLE \n" ) );

status = STATUS_SUCCESS;

break;}

case IOCTL_MOUNTMGR_QUERY_POINTS: // сообщить о символической ссылке для тома

{DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_MOUNTMGR_QUERY_POINTS\n" ) );

status = STATUS_INVALID_DEVICE_REQUEST;

break;}

case IOCTL_DISK_FORMAT_TRACKS: //Форматировать дорожки

{DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_FORMAT_TRACKS\n" ) );

status = STATUS_SUCCESS ;

break;}

case IOCTL_DISK_MEDIA_REMOVAL: //блокировать извлечение носителя

{DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_MEDIA_REMOVAL\n" ) );

status = STATUS_SUCCESS ;

break;}

case IOCTL_DISK_VERIFY: //провреить данные

{PVERIFY_INFORMATION verifyInformation;

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

status = STATUS_SUCCESS ;

break;}

case IOCTL_DISK_CHECK_VERIFY:// проверить, сменился ли носитель

{DBGPRINT( DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_CHECK_VERIFY\n" ) );

status = STATUS_SUCCESS ;

break;}

Запрос IOCTL_DISK_GET_PARTITION_INFO, требует сообщить информацию о разделах на диске. На рамдиске имеется один раздел. Результатом обработки запроса будет структура PARTITION_INFORMATION

typedef struct _PARTITION_INFORMATION

{LARGE_INTEGER StartingOffset; //смещение, с которого начинается раздел

LARGE_INTEGER PartitionLength;//размер раздела

DWORD HiddenSectors; //скрытых секторов

DWORD PartitionNumber; //порядковый номер раздела

BYTE PartitionType; //тип раздела

BOOLEAN BootIndicator; //TRUE - раздел является загрузочным

BOOLEAN RecognizedPartition; //распознан ли раздел

BOOLEAN RewritePartition; //TRUE - изменились параметры раздела}

Тип раздела PartitionType для виртуального диска может быть PARTITION_FAT_12 или PARTITION_FAT_16(он определяется при инициализации и хранится в расширении драйвера). Остальные поля заполняются следующим образом:

case IOCTL_DISK_GET_PARTITION_INFO:

{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... \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 Cylinders; //количество цилиндров

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

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

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

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

} 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!\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\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, поставляемого вместе с драйвером. Для установки фильтра необходимо выполнить следующие действия:

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

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

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

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

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

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

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

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

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

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

При необходимости настройки драйвера скопируйте файл 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.

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



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.