Обработка пакетов IRP в функции Startlo
Обработка пакетов IRP в функции Startlo
Как должна происходить обработка пакетов из системной очереди? Как уже говорилось, Startlo работает на уровне IRQL DISPATCHJLEVEL. Пока выполняется эта функция, ни один поток с более низким значением IRQL не может получить управление (если в системе один процессор). Следовательно, новые запросы ввода/ вывода от прикладных программ попасть в очередь не могут (потоки не выполняются). Если завершение очередного пакета ввода/вывода всегда происходит в функции Startlo, системная очередь всегда содержит не более одного пакета ввода/вывода. Если пакет ввода/вывода не может быть обработан в тот момент, когда он попал в функцию Startlo, функция просто должна завершиться, не завершая запрос ввода/ вывода и не вызывая IoStartNextPacket(). В этом случае устройство остается «занятым». Поле pDeviceObject->DeviceQueue.Busy все еще TRUE, а в поле pDevice-Object->CurrentIrp находится указатель на этот пакет IRP. Такой пакет может быть обработан, например, при поступлении прерывания от аппаратного устройства (или при возникновении другого ожидаемого события). Функция, которая завершит обработку такого пакета, обязана вызвать loStartNextPacket(), чтобы инициировать выборку очередного пакета из системной очереди. Заметим, что пока устройство остается «занятым», функция Startlo для обработки пакетов из системной очереди не может быть вызвана.
Несмотря на простоту использования системной очереди, имеется существенное ограничение. Оно состоит в том, что очередь одна на все типы запросов ввода/вывода (чтение, запись, управление устройством), В каждый конкретный момент обрабатывается только какой-то один пакет IRP.
Могут быть ситуации, когда такое ограничение неприемлемо. Классическим примером является драйвер полнодуплексного устройства, которое одновременно позволяет как отправлять, так и получать данные. В этом случае необходимо начать обработку следующего запроса чтения при завершении текущего запроса чтения, и следующего запроса записи при завершении текущего запроса записи. При этом важно понимать, что в этом случае одновременно (то есть в контекстах разных потоков) могут выполняться один запрос чтения и один запрос записи, Необходимы две очереди: одна - для запросов чтения, другая - для запросов записи.