Необходимость в создании рабочих потоков
Любой исполняемый код, как и код драйвера, работает в контексте некоторого
потока. Мы пока не обсуждали способы, с помощью которых драйвер может
создать собственный поток, поэтому предполагается, что поток, в котором
выполняется код драйвера, принадлежит некоторой прикладной программе.
Это означает, что прикладная программа создала такой поток для выполнения
своего кода, а не кода нашего драйвера. Если код драйвера производит длительную
обработку, либо драйвер использует механизм синхронизации с ожиданием
освобождения некоторого ресурса, код прикладной программы, для выполнения
которого и создавался поток, не выполняется. Если этот поток единственный
в прикладном процессе, то прикладная программа «висит».
Если описанная ситуация имеет место в диспетчерской функции драйвера верхнего
уровня, мы «всего лишь» «подвесили» прикладную программу, непосредственно
взаимодействующую с драйвером. В этом случае прикладная программа знает
о такой возможности, и может поместить операции взаимодействия с драйвером
(чтение, запись, отправка кодов управления) в отдельный поток. В этом
случае драйвер может не беспокоиться о прикладной программе. Однако, такая
ситуация довольно редка. Очень часто код драйвера работает в контексте
случайного потока, то есть любого произвольного потока в системе. Такой
поток ничего не знает о нашем драйвере и вышеописанная ситуация неприемлема.
В этом случае драйвер должен создать свой собственный поток, в котором
и производить длительную обработку, либо ожидание освобождения ресурсов.
Возможна другая ситуация, требующая обязательного создания потоков, когда
драйверу необходимо выполнить операции на уровне IRQL меньшем DISPATCHJLEVEL, а код драйвера работает на повышенных уровнях IRQL, больших или равных DISPATCH_LEVEL.