Автор: Пользователь скрыл имя, 29 Ноября 2011 в 19:08, курсовая работа
В настоящее время все усложняются программные продукты и комплексы, что приводит к росту объема обрабатываемых данных, усложнению структуры их представления и хранения на компьютере. Все это приводит к повышению требований к скорости чтения и записи данных из файлов а также уменьшению времени доступа к каждому файлу в отдельности.
ВВЕДЕНИЕ………………………………………………………………….3
1. АНАЛИТИЧЕСКИЙ РАЗДЕЛ
1.1. Постановка задачи………………………………………………………5
1.2. Архитектура Windows XP………………………………………………5
1.3. Многослойная архитектура драйверов………………………………...8
1.4. Архитектура драйверов устройств хранения………………………….9
1.5. Выбор файловой системы……………………………………………...11
……………………….38
FILE_DEVICE_DISK ,
(FILE_DEVICE_SECURE_OPEN),
FALSE,
&functionDeviceObject);
Если создание прошло успешно, мы читаем параметры диска из реестра и устанавливаем начальное состояние устройства остановлено (STOPPED) в расширении устройства, а также устанавливаем флаги сигнализирующие о том, что мы используем прямой метод передачи данных (DO_DIRECT_IO) и процедуры драйвера находятся в страничной памяти(DO_POWER_PAGABLE):
RamDskQueryDiskRegParameters
devExt->DevState = STOPPED; // состояние остановлен
// Установим флаги
functionDeviceObject->Flags |= DO_POWER_PAGABLE;
functionDeviceObject->Flags |= DO_DIRECT_IO;
// Резервируем память под образ диска
devExt->DiskImage =
ExAllocatePoolWithTag ( NonPagedPool,
devExt->DiskRegInfo.
RAMDSK_TAG_DISK ) ;
Последней операцией мы резервируем память в нестраничном пуле под образ диска(размер образа devExt->DiskRegInfo.DiskSize байт).
Т.к. выделенная память может содержать произвольные данные, необходимо записать метаданные файловой системы и подсчитать геометрию диска, что делается вызовом
RamDskFormatDisk( functionDeviceObject );
Создаем символическую ссылку, которая ассоциирует с нашим драйвером указанную в параметрах букву диска и имеет формат «\DosDevices\X:», где «Х» - буква диска.
RtlInitUnicodeString( &uniWin32Name, DOS_DEVICE_NAME );
devExt->SymbolicLink.
devExt->SymbolicLink.Length = uniWin32Name.Length;
RtlCopyUnicodeString( &(devExt->SymbolicLink), &uniWin32Name );
RtlAppendUnicodeStringToStri
// Создаем символьную ссылку в пространстве имен 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->
Последней
операцией устанавливается
3.4.2 Обработка запросов записи/чтения
Когда пользовательское приложение или компонент ядра пытается открыть драйвер виртуального диска для записи или чтения, то диспетчер ввода вывода формирует запросы IRP с кодом IRP_MJ_CREATE. При закрытии обрабатывается запрос IRP_MJ_CLOSE. Особых действий в обработке этих пакетов не требуется, поэтому драйвер возвращает успешный статус завершения. В данном драйвере оба пакета обрабатываются в одной процедуре RamDskCreateClose:
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
В качестве проверки, если мы получили пакет с другим кодом, то возвратим ошибочный статус.
Обработка
запросов на запись или чтение , также
реализуется в одной процедуре,
т.к. отличия в действиях
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.
RtlConvertUlongToLargeIntege
RtlConvertUlongToLargeIntege
(irpStack->Parameters.Read.
{DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR,
("Error invalid parameter\n"
"ByteOffset: %x\n"
"Length: %d\n"
"Operation: %x\n",
irpStack->Parameters.Read.
irpStack->Parameters.Read.
irpStack->MajorFunction));
status = STATUS_INVALID_PARAMETER;
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt-
return status;}
Если какой-либо из параметров не верен, то статус обработки запроса будет равен STATUS_INVALID_PARAMETER (неверные параметры).
Драйвер использует прямой метод передачи буфера данных, нам передается MDL список для буфера пользователя в параметре Irp->MdlAddress, который мы отображаем в адресное пространство ядра с помощью функции MmGetSystemAddressForMdlSafe:
ASSERT ( Irp->MdlAddress != NULL );
currentAddress
= MmGetSystemAddressForMdlSafe(
if ( currentAddress == NULL )
{status = STATUS_INSUFFICIENT_RESOURCES;
COMPLETE_REQUEST( Irp, status, information );
IoReleaseRemoveLock(&devExt-
DBGPRINT( DBG_COMP_READ, DBG_LEVEL_ERROR, ("Unable to get the system-space virtual address\n" ) );
return status;}
Когда адрес получен адрес буфера (currentAddress), можно произвести копирование данных с помощью функции RtlMoveMemory
information
= irpStack->Parameters.Read.
switch (irpStack->MajorFunction)
{case IRP_MJ_READ:
RtlMoveMemory(
currentAddress,
devExt->DiskImage
+ irpStack->Parameters.Read.
irpStack->Parameters.Read.
break;
case IRP_MJ_WRITE:
RtlMoveMemory(
devExt->DiskImage
+ irpStack->Parameters.Read.
currentAddress,
irpStack->Parameters.Read.
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\
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; //смещение, с которого начинается раздел
LARGE_INTEGER;//размер раздела
DWORD; //скрытых секторов
DWORD; //порядковый номер раздела
BYTE; //тип раздела
BOOLEAN; //TRUE - раздел является загрузочным
BOOLEAN; //распознан ли раздел
BOOLEAN; //TRUE – изменились параметры раздела}
Тип раздела для виртуального диска может быть PARTITION_FAT_12 или PARTITION_FAT_16(он определяется при инициализации и хранится в расширении драйвера). Остальные поля заполняются следующим образом:
case IOCTL_DISK_GET_PARTITION_INFO:
{DBGPRINT(
DBG_COMP_IOCTL, DBG_LEVEL_INFO, ("IOCTL_DISK_GET_PARTITION_
if
(irpStack->Parameters.
{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.
outputBuffer->PartitionType
= (UCHAR)devExt->DiskRegInfo.
outputBuffer->BootIndicator = FALSE;
outputBuffer->