Процедуры отложенного вызова обслуживания прерываний DpcForIsr
Вызов процедуры DpcForIsr может быть запланирован из собственно ISR процедуры вызовом IoRequestDpc. Прототип этой функции драйвера описан в таблице 8.13.
Таблица 8.13. Прототип функции для процедуры DpcForIsr
VOID DpcForIsr | IRQL == DISPATCH_LEVEL |
Параметры | Завершает обработку прерывания, начатую в ISR процедуре драйвера |
IN PKDPC pDpc | DPC-объект |
IN PDEVICE_OBJECT pDevObj | Указатель на объект устройства, для которого зарегистрирована данная DPC процедура |
IN PIRP pIrp | Интересующий пакет IRP |
IN VOID pContext | Контекстный указатель, переданный вызовом IoRequestDpc |
Возвращаемое значение | void |
При анализе прототипа вызова IoRequestDpc и примера кода перед таблицей 8.13, возникает правомерный вопрос: вызов какой функции планирует ISR процедура, выполняя вызов IoRequestDpc? Ведь DpcForIsr функция не фигурирует ни при регистрации ISR процедуры вызовом IoConnectInterrupt, ни в тексте OnInterrupt.
Ответ состоит в том, что DpcForIsr регистрируется для конкретного объекта устройства вызовом IoInitializeDpcRequest (см. таблицу 8.14). Если обратить внимание на структуру DEVICE_OBJECT, описанную в заголовочных файлах wdm.h и ntddk.h (см. пакет DDK), то несложно заметить поле 'KDPC Dpc', предназначенное как раз для хранения DPC объекта. Соответственно, выполняя вызов IoRequestDpc
c указателем на объект устройства в качестве первого аргумента, ISR процедура драйвера однозначно определяет, какая именно DpcForIsr функция будет вызвана позже — хранящаяся в объекте устройства.
Таблица 8.14. Прототип вызова IoInitializeDpcRequest
VOID IoInitializeDpcRequest | IRQL == PASSIVE_LEVEL |
Параметры | Регистрирует DpcForIsr процедуру для данного объекта устройства, создает и инициализирует DPC объект |
IN PDEVICE_OBJECT pDevObj | Указатель на объект устройства, для которого регистрируется данная DPC процедура |
IN VOID (*DpcForIsr) | Адрес DpcForIsr процедуры, которая должна иметь прототип, описанный в таблице 8.13 |
Возвращаемое значение | void |
Регистрацию DpcForIsr процедуры (и ее связывание с объектом устройства) для PnP драйверов рекомендуется делать в процедуре AddDevice драйвера.
Первый параметр pDpc в описании прототипа процедуры DpcForIsr (таблица 8.13) не должен пугать разработчика. Если используется вызов IoInitializeDpcRequest, то именно он создает данный объект, а в вызов DpcForIsr поступит указатель на уже готовый DPC объект. |