Драйвер виртуального диска

Автор: Пользователь скрыл имя, 29 Ноября 2011 в 19:08, курсовая работа

Описание работы

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

Содержание

ВВЕДЕНИЕ………………………………………………………………….3
1. АНАЛИТИЧЕСКИЙ РАЗДЕЛ
1.1. Постановка задачи………………………………………………………5
1.2. Архитектура Windows XP………………………………………………5
1.3. Многослойная архитектура драйверов………………………………...8
1.4. Архитектура драйверов устройств хранения………………………….9
1.5. Выбор файловой системы……………………………………………...11
……………………….38

Работа содержит 1 файл

Курсовой проект 1.doc

— 369.00 Кб (Скачать)

  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:

  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; //смещение, с которого начинается раздел

  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_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

Информация о работе Драйвер виртуального диска