2. КОНСТРУКТОРСКИЙ РАЗДЕЛ
2.1 Структура классового драйвераДрайвер реализуется как набор процедур, каждая из которых предназначена для реализации отдельного типа обращений к драйверу со стороны диспетчера ввода/вывода. Процедуры, которые необходимо поддерживать классовому драйверу приведены в таблице 1.
Таблица 1
Процедура | Описание |
DriverEntry | Выполняется при загрузке драйвера операционной системой. Здесь драйвер регистрирует свои остальные точки входа и выполняет свою общую инициализацию. |
Unload | Вызывается при выгрузке драйвера. Здесь необходимо освободить все затребованные ресурсы. |
AddDevice | Здесь создаётся объект-устройство, соответствующий полученному уведомлению от менеджера устройств, и выполняется инициализация данных, специфичных для данного устройства. |
DispatchPnP | Выполняет обработку специфичных Plug&Play запросов , таких как инициализация устройства, таких как инициализация устройства, остановка, удаление устройства и обрабатывать остальные запроса |
DispatchPower | Выполняет обработку запросов по управлению питанием устройства |
DispatchSystemControl | Обрабатывает запросы от подсистемы инструментария Windows (WMI) |
DispatchCreate, DispatchClose, DispatchRead, DispatchWrite | Обслуживают запросы на чтение запись данных для устройства. |
Определим, какую структуру данных оптимально использовать для хранения данных на диске. Самый простой способ – разместить все данные в одномерном массиве байт, и адресовать данные с помощью смещения от начала диска. Следует учесть тот факт, что при запросах на чтение /запись данных, в качестве параметров указывается : смещение в байтах с которого начинается передача данных (которое и служит индексом первого байта для чтения) и количество байт для передачи.
Естественно, что применение более сложных структур организации данных(двумерный массив, списки и т.д.) приведет только к дополнительным накладным расходам по преобразованию адресации данных.
Таким образом, виртуальный диск будет храниться в памяти как одномерный массив байт заданного размера. Для чтения данных, информация копируется из области памяти образа диска в буфер инициатора запроса. Для записи - копирование происходит в обратном направлении.
Следующим шагом выберем, каким образом мы зарезервируем память для диска. Для резервирования памяти в режиме ядра Windows предоставляет специальные системные вызовы. Существуют следующие типы резервируемой памяти:
· Страничная память(Paged memory) – виртуальная память, которая может быть перемещена системой на жесткий диск в любой момент времени. В случае, если приложение обратиться к отсутствующей в физической памяти области своей виртуальной памяти, то возникает исключение по отсутствию страницы в памяти. В результате системный обработчик перехватывает это исключение и загружает в физическую память отсутствующую страницу. Однако при работе в режиме ядра, когда уровень приоритета равен или выше DISPATCH_LEVEL, это исключение создаст ситуацию, когда системный обработчик не может подгрузить страницу т.к. его IRQL меньше текущего.
· Нестраничная память(Nonpaged memory) – эта память никогда не может быть перемещена системой на жесткий диск и всегда остается в физической оперативной памяти. В результате, обращаться к этой памяти можно при любом уровне IRQL. Объем данной памяти ограничен даже при наличии достаточного объема физической памяти в Windows 2000 660 Мбайтами, а в Windows XP 1300 Мбайтами.
Поскольку обращение к образу диска происходит при уровне привилегий PASSIVE_LEVEL или DISPATCH_LEVEL, но в особых ситуациях этот приоритет может быть выше. Поэтому во избежание возникновения ситуации, когда страница отсутствует в памяти, и мы ее не сможем подгрузить – виртуальный диск будет использовать нестраничную память. Дополнительно мы увеличим быстродействие драйвера, т.к. уже не требуется подгружать отсутствующие страницы с жесткого диска.
2.3 Доступ к передаваемым даннымРассмотрим, каким образом драйвер может получить доступ к передаваемым данным. Пользовательский процесс, вызывая функцию API (например, WriteFile), передаёт ей указатель на буфер, в котором размещается записываемая информация. Однако, передаваемый виртуальный адрес действительно будет указывать на записываемую информацию только в контексте данного процесса. Операции же ввода/вывода в драйвере происходят в контексте произвольного процесса. Из-за смены таблиц страничного преобразования при переключении процессов использовать переданный виртуальный адрес в произвольном контексте совершенно недопустимо.
Для операций ввода/вывода архитектура операционной предусматривает два специальных метода передачи буфера данных, принадлежащего инициатору запроса:
· Буферизированный (buffered I/O). Драйверу в пакете запроса ввода/вывода передаётся указатель на копию исходного буфера в невыгружаемой памяти (поле AssociatedIrp.SystemBuffer). Подсистема ввода/вывода отвечает за точное соответствие содержимого этого буфера передаваемым данным. Этот метод, в основном, используется для устройств, не предающих больших объёмов данных: манипуляторы, низкоскоростные коммуникационные линии и т. п.
· Прямой (direct I/O). В этом случае система блокирует страницы пользовательского буфера, чтобы они не были выгружены на диск во время передачи данных. Расположение пользовательского буфера в физической памяти описывается структурой MDL (Memory Descriptor List), доступной в пакете запроса ввода/вывода через поле MdlAddress. По этой структуре необходимо настроить системную таблицу страниц на тот же буфер в физической памяти. Это осуществляется функцией MmGetSystem, которая возвращает виртуальный адрес буфера в системной области памяти. Данный метод эффективен с большими объёмами данных, например, при работе с дисковыми накопителями.
Для драйвера виртуального диска будет использоваться прямой метод, который обеспечивает возможность обмена большими данными и высокую скорость передачи.
2.4 Обработка запросов Plug and PlayВ процессе работы диспетчер ввода вывода может динамически управлять состоянием устройства: запускать, останавливать и выгружать. Реализация этих функций драйвером устройства хранения обеспечивает при обработке специфичных PnP IRP пакетов. В таблице 2 приведены описания IRP пакетов, которые должны поддерживаться.
Таблица 2
IRP_MN_Xxx | Описание |
IRP_MN_START_DEVICE | Инициализация устройства с заданными ресурсами |
IRP_MN_QUERY_STOP_DEVICE | Проверка осуществимости остановки устройства для перераспределения ресурсов |
IRP_MN_STOP_DEVICE | Остановка устройства с потенциальной возможность. перезапуска или удаления из системы |
IRP_MN_CANCEL_STOP_DEVICE | Уведомляет, что предыдущий запрос на остановку не получит дальнейшего развития |
IRP_MN_QUERY_REMOVE_DEVICE | Проверка осуществимости безопасного удаления устройства |
IRP_MN_REMOVE_DEVICE | Выполнить безопасное удаление устройства |
IRP_MN_CANCEL_REMOVE_DEVICE | Уведомляет, что предыдущий запрос на удаление не получит дальнейшего развития |
IRP_MN_SURPRISE_REMOVAL | Уведомляет, что устройство было удалено без предварительного предупреждения |
Применительно к виртуальному диску большая часть этих сообщений не влечет каких-либо дополнительных действий, т.к. у рамдиска нет дополнительных буферов, данные с которые должны быть записаны на диск при остановке устройства, или поддержки функций управления электропитанием устройства. Поэтому для виртуального диска существует внутренняя переменная, которая хранит текущее состояние устройства.
Основным состоянием диска будет WORKING – когда диск находится в рабочем состоянии. Остальные состояния(приведенные в таблице 3) носят информативный характер, чтобы узнать текущий режим работы диска. При операциях доступа к устройству будет осуществляться проверка состояния WORKING, и только при нем доступ к диску разрешен.
Таблица 3
Состояние | Значение |
STOPPED | Устройство остановлено |
WORKING | Устройство работает |
PENDINGSTOP | Устройство ожидает остановки |
PENDINGREMOVE | Устройство ожидает удаления |
SURPRISEREMOVED | Устройство удалено без предварительного предупреждения |
REMOVED | Устройство удалено |
UNKNOWN | Устройство в ошибочном состоянии |
Для управления сами устройством диспетчер ввода вывода посылает драйверу пакет с кодом управления вводом/выводом(IOCTL). Какие именно коды управления будет посылаться зависит от типа устройства. О том какие коды должен обязательно поддерживать классовый драйвер точно ничего не сказано. Поэтому приведенный далее список кодов управления был получен в процессе отладки драйвера, когда записывались получаемые драйвером IOCTL и выяснялась их функция.
Список кодов управления:
· IOCTL_DISK_GET_PARTITION_INFO – сообщить о типе, размере и природе раздела диска.
· IOCTL_DISK_GET_MEDIA_TYPES,
IOCTL_DISK_GET_DRIVE_GEOMETRY – сообщить о геометрии диска (количество цилиндров, дорожек, секторов)
· IOCTL_DISK_IS_WRITABLE – проверка можно ли на диск записывать данные
· IOCTL_DISK_SET_PARTITION_INFO – изменить тип раздела
· IOCTL_MOUNTMGR_QUERY_POINTS – сообщить о символической ссылке для тома
· IOCTL_MOUNTDEV_QUERY_DEVICE_NAME – сообщить об имени устройства
· IOCTL_DISK_FORMAT_TRACKS – форматировать дорожки
· IOCTL_DISK_MEDIA_REMOVAL – блокировать извлечение носителя
· IOCTL_DISK_CHECK_VERIFY – проверить, сменился ли носитель (для съемных дисков)
2.6 Расчет геометрии дискаПри получении расширенного запроса IOCTL_DISK_GET_DRIVE_GEOMETRY или IOCTL_DISK_GET_MEDIA_TYPES требуется инициатору запроса передать информацию о геометрии диска. Драйвер виртуального диска заполняет стандартную структуру Windows DISK_GEOMETRY, где указываются следующие параметры:
Cylinders – количество цилиндров
TracksPerCylinder – количество дорожек на цилиндр
SectorsPerTrack – количество секторов на дорожку
BytesPerSector – размер сектора в байтах
MediaType – тип носителя
Тип носителя для жестких дисков должен быть равен FixedMedia.
Размер сектора примем равным 512 байтам, это стандарт де-факто для почти всех современных дисковых накопителей.
Количество дорожек и секторов будет фиксированным
TracksPerCylinder = 16 SectorsPerTrack = 32
Вычисляем количество цилиндров диска:
Cylinders = DiskSize /(BytesPerSector*SectorsPerTrack* TracksPerCylinder),
где DiskSize – размер диска.
Если количество цилиндров превышает 1023(такое ограничение было введено для совместимости со старыми версиями BIOS), то количество секторов на дорожку увеличивается вдвое и будет равно 64.
Таким образом максимальный размер рамдиска, для которого число цилиндров не превышает 1023 равен:
MaxDiskSize = 1023*16*64*512 = 536346624 байт= 511.5 Мбайт,
что более чем достаточно для нашей версии рамдиска.
... загрузочные сектора жестких дисков. Физическое и логическое подключение жестких дисков Какие же необходимо подключить разъемы и установить перемычки и другие операции при физической установке накопителя на жестких дисках? Это - интерфейсный шлейф, кабель питания, перемычки выбора статуса логического устройства и, возможно, индикатор состояния устройства (обращения к устройству), а также ...
... случае драйвера устройства, поддерживающего только один тип носителя (например драйвер RAM-диска), содержимое BPB может быть закодировано в теле самого драйвера. К несчастью, при работе с реальными дисками, включая жесткие диски, не все так просто и драйвер обязан определять содержимое BPB. Как правило, BPB является частью блока начальной загрузки, как показано на рис.6-7. В этом ...
аучного цикла является отсутствие возможности реальной постановки учебного, и лабораторного эксперимента. Хотя в настоящее время имеются разработки виртуальных лабораторных практикумов, однако окончательно решение проблемы требует пристального внимания специалистов различных профилей, в том числе и психолого-педагогического. 1.2 Роль технологии виртуальных приборов обучения в техническом вузе ...
... ) ФАКУЛЬТЕТ ЭЛЕКТРОНИКИ И ПРИБОРОСТРОЕНИЯ КАФЕДРА КЭС группа Э-92 ДАТА ЗАЩИТЫ апреля 1997 г. Отзыв на дипломную работу студента гр.Э-92 Сорокина Ю.В. “Разработка программы контроллера автоматически связываемых объектов для управления конструкторской документацией в среде Windows 95/NT”. Широкое использование вычислительной техники в народном хозяйстве требует увеличения производства и ...
0 комментариев