Драйвер устройства IRQL и переключатели потоков / контекстов - PullRequest
3 голосов
/ 22 февраля 2010

Я новичок в программировании драйверов устройств Windows. Я знаю, что некоторые операции можно выполнять только на IRQL PASSIVE_LEVEL. Например, Microsoft имеет следующий пример кода для записи в файл из драйвера ядра:

if (KeGetCurrentIrql() != PASSIVE_LEVEL)
    return STATUS_INVALID_DEVICE_STATE; 

Status = ZwCreateFile(...);

У меня такой вопрос: что мешает поднять IRQL после проверки KeGetCurrentIrql() выше? Скажем, происходит смена контекста или потока, может ли IRQL внезапно стать DISPATCH_LEVEL, когда он вернется к моему драйверу, что приведет к сбою системы?

Если это НЕ возможно, то почему бы просто не проверить IRQL в функции DriverEntry и покончить с этим раз и навсегда?

Ответы [ 3 ]

2 голосов
/ 03 апреля 2010

IRQL может меняться только под вашим контролем, если вы его настроите. Существует два IRQL, ориентированных на потоки - PASSIVE_LEVEL и APC_LEVEL. Вы управляете входом и выходом из этих уровней с помощью таких вещей, как быстрые мьютексы, и переключение контекста на ваш поток всегда оставит вас на том уровне, на котором вы были раньше. Выше это "специфичные для процессора" IRQL. Это DISPATCH_LEVEL или выше. На этих уровнях переключение контекста не может происходить. Вы попадаете на эти уровни, используя спин-блокировки и тому подобное. ISR будут встречаться при более высоких IRQL в вашем потоке, но вы их не видите. Когда они вернут вам управление, ваш IRQL восстановится.

2 голосов
/ 22 февраля 2010

IRQL потока может быть поднят только сам по себе.

Поскольку вы вызываетесь из верхних / нижних драйверов, irql текущего запущенного контекста может отличаться. И есть пара функций, которые поднимают / опускают irql.

Пара примеров:

IRP_MJ_READ

   NTSTATUS DispatchRead(
    __in struct _DEVICE_OBJECT  *DeviceObject,
    __in struct _IRP  *Irp
    )
  {
     // this will be called at irql == PASSIVE_LEVEL
     ...
     // we have acquire a spinlock
     KSSPIN_LOCK lck;
     KeInititializeSpinLock( &lck );
     KIRQL prev_irql;
     KeAcquireSpinLock( &lck,&prev_irql );

     // KeGetCurrentIrql() == DISPATCH_LEVEL 

     KeReleaseSpinLock( &lck, prev_irql );
     // KeGetCurrentIrql() == PASSIVE_LEVEL 
     ...
  }

(Io-) Процедуры завершения могут быть вызваны в DISPATCH_LEVEL и поэтому должны вести себя соответственно.

NTSTATUS CompleteSth(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)
{
    // KeGetCurrentIrql() >= PASSIVE_LEVEL
}
0 голосов
/ 31 марта 2010

DriverEntry также вызывается на PASSIVE_LEVEL.

Если вы хотите, чтобы работа выполнялась в PASSIVE_LEVEL, используйте такие функции, как IoQueueWorkItem

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...