- •Лекция №10. Сериализация. System Queuing и Driver Queuing
- •[10.1] Завершение запроса в/в.
- •[10.2] Задержка обработки запросов irp и постановка запросов irp в очередь [10.2.1] Задержка обработки запросов irp
- •[10.2.2] Постановка запросов irp в очередь
- •[10.2.2.1] Системная очередь запросов irp (System Queuing)
- •[10.2.2.1.1] Обработка пакетов irp в функции StartIo
- •[10.2.2.2] Очереди, управляемые драйвером
- •[10.2.2.2.1] Функции управления очередью низкого уровня
- •[10.2.2.2.2] Функции управления очередью высокого уровня – “Очередь Устройства” (Device Queue)
- •[10.3] Отмена запросов в/в
- •[10.3.1] Отмена irp и Системная Очередь
- •[10.3.2] Отмена irp и очереди, управляемые драйвером
Лекция №10. Сериализация. System Queuing и Driver Queuing
Сериализация – процесс выполнения различных операций в нужной последовательности.
Функция драйвера для обработки запроса в/в может быть вызвана из различных потоков различных процессов. Неэксклюзивное устройство может быть одновременно открыто несколькими прикладными программами, каждая из которых может послать один и тот же запрос в одно и то же время. Нам необходимо, чтобы обработка каждого такого запроса началась как можно быстрее, но не раньше, чем завершится обработка предыдущего запроса.
Если устройство эксклюзивное и вся обработка завершается в диспетчерской функции, сериализация обеспечивается операционной системой. Диспетчерские функции работают в контексте памяти потока-инициатора запроса в/в, следовательно, пока не завершится диспетчерская функция, код прикладной программы не получит управления и не инициирует очередной запрос в/в.
Однако даже эксклюзивное устройство может не суметь обработать запрос в/в в диспетчерской функции сразу при его поступлении. Если драйвер будет ждать в диспетчерской функции возможности обработать и завершить запрос, прикладная программа – инициатор запроса будет “висеть” – ее код не выполняется. Более того, если такой драйвер является уровневым и не является драйвером верхнего уровня, его диспетчерские функции будут вызываться в случайном контексте потока. “Завесив”свою диспетчерскую функцию, драйвер “завесит” произвольный поток произвольной прикладной программы! Чтобы так не происходило, диспетчерская функция должна завершиться как можно скорее. При этом диспетчеру в/в необходимо указать, что соответствующий запрос в/в не был завершен, однако это не ошибка, и этот запрос в/в будет завершен когда-то позже. При этом возникают вопросы:
как указать, что запрос в/в не завершен;
где хранить незавершенные пакеты в/в;
как быть, если запрос в/в не завершен, а инициировавшее запрос приложение закрылось.
[10.1] Завершение запроса в/в.
Успешное завершение запроса в/в в диспетчерской функции показано в следующем листинге:
Irp->IoStatus.Status =STATUS_SUCCESS;
Irp->IoStatus.Information =bytesTransfered;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
При неудачном завершении обработки запроса в/в в поле Irp->IoStatus.Status устанавливается код ошибки (значение, не равное STATUS_SUCCESS), оно же возвращается оператором return.
[10.2] Задержка обработки запросов irp и постановка запросов irp в очередь [10.2.1] Задержка обработки запросов irp
Когда немедленное завершение запроса в/в в диспетчерской функции невозможно, драйвер должен указать диспетчеру в/в, что обработка запроса продолжается. Для этого возвращаемым значением диспетчерской функции должно быть значение STATUS_PENDING. Перед этим в самом пакете IRP в текущем стеке размещения в/в должен быть установлен флаг SL_PENDING_RETURNED, помечающий запрос как неоконченный. Для этого служит функция IoMarkIrpPending().
VOID IoMarkIrpPending(IN PIRP Irp);
Установка этого флага указывает, что IRP будет освобожден драйвером с помощью вызова IoCompleteRequest() когда-то потом.
[10.2.2] Постановка запросов irp в очередь
Для постановка IRPв очередь диспетчерская функция должна:
пометить IRPкак неоконченный
установить функцию отмены IRP
использовать один из нижеприведенных способов для постановки IRP в очередь
завершиться со статусом STATUS_PENDING.
NT предусматривает два способа организации очередей пакетов IRP:
Использование диспетчера в/в для постановки запросов в управляемую им очередь (Системная Очередь).
Создание и управление очередью самостоятельно (Очереди, управляемые драйвером).