1.6 Уровни запроса прерываний

В каждый момент времени центральный процессор находится на одном из уровней IRQL (Interrupt Request Level – уровень запросов прерываний). Уровни IRQL располагаются в порядке убывания от HIGHEST_LEVEL до PASSIVE_LEVEL. Каждому из прерываний (прерывания от внешних устройств, системные часы, и т.д.) соответствует свой уровень IRQL. Специальным действиям операционной системы также назначены IRQL. Они отмечены в нижней части приведённой таблицы:

Таблица 1.6.1. Уровни запросов прерываний.

Уровень

Назначение

HIGHEST_LEVEL Наивысший уровень. Все прерывания заблокированы
POWER_LEVEL Прерывания по отказу питания
IPI_LEVEL Межпроцессорное взаимодействие
CLOCK2_LEVEL Прерывание по системному таймеру 2
СLOCK1_LEVEL Прерывание по системному таймеру 1
PROFILE_LEVEL Прерывание по таймеру замера производительности
уровни DRQL Обычные прерывания устройств
DISPATCH_LEVEL Диспетчеризация потоков и выполнение отложенных процедур
APC_LEVEL Выполнение асинхронного вызова процедуры
PASSIVE_LEVEL Обычное исполнение кода потока

Общее правило обработки уровней запросов прерываний гласит, что прерывания с IRQL, меньшим, чем у выполняемого в данный момент кода, маскируются. Во время исполнения кода потока (пользовательского или системного) устанавливается наименьший IRQL = 0 (PASSIVE_LEVEL). Работа драйвера чаще всего выполняется на уровне IRQL = 2 (DISPATCH_LEVEL). Уровни, лежащие над ним, называются DIRQL (Device IRQL) и выставляются для обработчиков прерываний от внешних устройств (ISR – interrupt service routine). Даже во время выполнения ISR драйвера может произойти прерывание с большим IRQL, например, принадлежащее другому драйверу.

Чем выше текущий уровень IRQL исполняемого кода, тем меньше функций ему доступно. Так, например, диспетчер потоков работает на уровне
DISPATCH_LEVEL, и, следовательно, не будет вызываться, пока на процессоре с уровнем большим или равным DISPATCH_LEVEL исполняется другой код. Таким образом, на уровнях DISPATCH_LEVEL и выше отключается переключение потоков. Функции ожидания диспетчерских объектов (события, мьютексы, семафоры) с отличным от нуля временем, обращение к файлам, подкачка отсутствующих в физической памяти страниц – всё это также становится недоступным. Для корректного сохранения запросов в файле фильтр в таких случаях должен применять специальную методику.

1.7 Уведомление о завершении запроса нижестоящим драйвером

При отслеживании обмена данными драйвер-фильтр может получать уведомления о том, что некоторый переданный запрос был завершён нижестоящим драйвером. Механизм уведомления заключается в том, что вызовом специальной функции IoSetCompletionRoutine фильтр обращается к стеку в пакете IRP. В позиции стека, следующей за текущей позицией, он устанавливает в специальном поле адрес функции завершения (completion routine). Затем при передаче пакета по цепочке позиция стека увеличивается.

Когда нижестоящий драйвер отправляет пакет запроса на завершение (вызовом IoCompleteRequest), подсистема ввода / вывода начинает просматривать стек внутри этого пакета от конца к началу. Если в какой-то позиции стека определена функция завершения, управление передаётся ей. Отработав, функция возвращает результат, сигнализирующий об успехе, ошибке или необходимости дальнейшей обработки запроса.

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

При третьем же варианте просмотр стека немедленно прекращается и запрос не будет завершён. Эта возможность реализована для того, чтобы драйвер-фильтр мог выполнить какие-либо действия над пакетом запроса после того, как тот будет обработан в нижестоящем драйвере. После такой «дополнительной обработки» пакет снова должен быть отправлен на завершение.

1.8 Работа с файлами в режиме ядра

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

Для открытия файла из драйвера режима ядра используется универсальная функция ZwCreateFile. Универсальность этой функции состоит в том, что с ее помощью производится и открытие существующих файлов, и создание новых.

Специфика системной функции ZwCreateFile состоит в том, что она имеет протокольных параметров даже больше, чем пользовательский вызов CreateFile. Существенная часть входной информации об открываемом объекте поступает внутри структуры OBJECT_ATTRIBURTES, которую следует предварительно создать и заполнить соответствующими конкретными данными. Для ведения учетной информации открытого объекта используется структура данных IO_STATUS_BLOCK, которую следует предоставить при вызове (инициализировать ее не следует).

Представим основные параметры функции ZwCreateFile в следующей таблице:

 

Таблица 1.8.1. Параметры функции ZwCreateFile

Тип параметра

Описание параметра

OUT PHANDLE pHandle Указатель на переменную, куда следует поместить дескриптор открытого объекта
IN ACCESS_MASK DesiredAccess

Характеристика доступа к объекту. Для фалов чаще всего используются значения

GENERIC_READ или GENERIC_WRITE

IN POBJECT_ATTRIBUTES

pObjAttributes

Указатель на заполненную вызывающим кодом структуру данных, которая описывает имя, местоположение и некоторые другие характеристики открываемого объекта
OUT PIO_STATUS_BLOCK pIOStatus Указатель на буфер, в котором будет размещена информация об открытом объекте в формате структуры IO_STATUS_BLOCK
IN PLARGE_INTEGER AllocationSize Начальный размер файла в байтах. Ненулевое значение принимается во внимание только при создании и перезаписи файла
IN ULONG FileAttributes Атрибуты открываемого файла. Типовым является значение FILE_ATTRIBUTE_NORMAL
IN ULONG SharedAccessFlags Описывает, разрешен ли совместный доступ, например, FILE_SHARE_READ – для чтения
IN ULONG CreateDispositionFlags Способ открытия файла, например, FILE_OPEN_IF – если не существует, создать
IN ULONG CreateOptions Комбинация флагов создания, например, FILE_SYNCHONOUS_IO_NONALERT – все операции над файлом выполняются как синхронные (DesiredAccess должен включать флаг SYNCHRONIZE)
IN PVOID EaBuffer Для драйверов устройств следует указывать NULL
IN ULONG EaLength Для драйверов устройств следует указывать 0

Для заполнения структуры атрибутов объекта используется функция
InitializeObjectAttributes. Опишем ее параметры в следующей таблице:

 

Таблица 1.8.2. Параметры функции InitializeObjectAttributes

Тип параметра

Описание параметра

OUT POBJECT_ATTRIBUTES pObjAttributes Указатель на переменную, куда следует поместить атрибуты объекта
IN PUNICODE_STRING ObjectName Имя объекта, HANDLE которого создается
IN ULONG Attributes Флаги атрибутов объекта, при открытии файла как правило используются флаги OBJ_CASE_INSENSITIVE и OBJ_KERNEL_HANDLE
IN HANDLE RootDirectory Дескриптор корневой директории для объекта, описатель атрибутов которого создается. Если ObjectName полностью описывает путь к объекту, то значению RootDirectory присваивается NULL
IN PSECURITY_DESCRIPTOR SecurityDescriptor Дескриптор безопасности. Если указано NULL, то применяется стандартный дескриптор

Запись в файл выполняется системной функцией ZwWriteFile:

 

Таблица 1.8.3. Параметры функции ZwWriteFile

Тип параметра

Описание параметра

IN HANDLE FileHandle Дескриптор открытого или модифицированного файлового объекта
IN HANDLE Event Для драйверов устройств следует указывать NULL
IN PIO_APC_ROUTINE Для драйверов устройств следует указывать NULL
IN PVOID ApcContext Для драйверов устройств следует указывать NULL
OUT PIO_STATUS_BLOCK pioStatusBlock В поле pIoStatusBlock->Information по завершении вызова находится число реально записанных байт
IN PVOID Buffer Буфер с данными для записи
IN ULONG Length Размер записываемой порции данных
IN PLARGE_INTEGER pByteOffset Указатель на переменную где содержится смещение в файле от его начала, по которому следует производить запись
IN PULONG Key Для драйверов устройств следует указывать NULL

Для закрытия дескриптора объекта следует применять функцию ZwCloseKey.

Следует отметить, что функции работы с файлами могут работать только на уровне IRQL, равном PASSIVE_LEVEL. Это приводит к необходимости применения специальной методики при протоколировании обмена данными с USB‑накопителем.


Информация о работе «Протоколирование обмена информацией между компьютером и внешним запоминающим USB-устройством»
Раздел: Информатика, программирование
Количество знаков с пробелами: 58963
Количество таблиц: 10
Количество изображений: 6

Похожие работы

Скачать
79890
1
0

... системы и их особенностями в целом, мы разобрались, теперь самое время приступить к более детальному, конкретному рассмотрению многообразия ОС, которое обычно начинается с рассмотрения краткой истории появления и развития. Операционная система Unix Считается, что в появлении Юникса в частности виновата... компьютерная игра. Дело в том, что Кен Томпсон непонятно чего ради создал игрушку «Space ...

0 комментариев


Наверх