Сериализация
Сериализация - это процесс выполнения различных операций
в нужной последовательности.
Функция драйвера для обработки запроса ввода/вывода может быть вызвана
из различных потоков различных процессов. Неэксклюзивное устройство может
быть одновременно открыто несколькими прикладными программами, каждая
из которых может послать один и тот же запрос в одно и то же время. Нам
необходимо, чтобы обработка каждого такого запроса началась как можно
быстрее, но не раньше, чем завершится обработка предыдущего запроса.
Если устройство эксклюзивное и вся обработка завершается в диспетчерской
функции, Сериализация обеспечивается операционной системой. Диспетчерские
функции работают в контексте памяти потока-инициатора запроса ввода/вывода,
следовательно, пока не завершится диспетчерская функция, код прикладной
программы не получит управления и не инициирует очередной запрос ввода/вывода.
Однако даже эксклюзивное устройство может не суметь обработать запрос
ввода/ вывода в диспетчерской функции сразу при его поступлении. Если
драйвер будет ждать в диспетчерской функции возможности обработать и завершить
запрос, прикладная программа - инициатор запроса будет «висеть» - ее код
не выполняется. Более того, если такой драйвер является уровневым и не является драйвером верхнего уровня, его диспетчерские функции будут вызываться в случайном контексте потока. «Завесив» свою диспетчерскую функцию, драйвер «завесит» произвольный поток произвольной прикладной программы! Чтобы такого не происходило, диспетчерская функция должна завершиться как можно скорее. При этом диспетчеру ввода/вывода необходимо указать, что соответствующий запрос ввода/вывода не был завершен, однако это не ошибка, и этот запрос ввода/вывода будет завершен когда-то позже. При этом возникают вопросы:
- как указать, что запрос ввода/вывода не завершен;
- где хранить незавершенные пакеты ввода/вывода;
- как быть, если запрос ввода/вывода не завершен, а инициировавшее запрос приложение закрылось.
Завершение запроса ввода/вывода.
Успешное завершение запроса ввода/вывода в диспетчерской функции показано
в следующем листинге: Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information
= bytesTransfered; loCompleteRequest (Irp, IO_NO_INCREMENT); return STATUS
SUCCESS;
При неудачном завершении обработки запроса ввода/вывода в поле Irp->IoStatus.Status
устанавливается код ошибки (значение, не равное STATUS_SUCCESS), оно же
возвращается оператором return.