Configurando e usando filas de dispositivos
Um driver configura um objeto de fila de dispositivo chamando KeInitializeDeviceQueue na inicialização do driver ou do dispositivo. Depois de iniciar seus dispositivos, o driver insere IRPs nessa fila chamando KeInsertDeviceQueue ou KeInsertByKeyDeviceQueue. A figura a seguir ilustra essas chamadas.
Como mostra essa figura, o driver deve fornecer o armazenamento para um objeto de fila do dispositivo, que deve ser residente. Os drivers que configuram um objeto de fila de dispositivo geralmente fornecem o armazenamento necessário na extensão do dispositivo de um objeto de dispositivo criado pelo driver, mas o armazenamento pode estar em uma extensão de controlador se o driver usar um objeto de controlador ou em um pool nãopagado alocado pelo driver.
Se o driver fornecer armazenamento para o objeto de fila do dispositivo em uma extensão de dispositivo, ele chamará KeInitializeDeviceQueue depois de criar o objeto do dispositivo e antes de iniciar o dispositivo. Em outras palavras, o driver pode inicializar a fila de sua rotina AddDevice ou quando lida com uma solicitação de IRP_MN_START_DEVICE PnP. Na chamada para KeInitializeDeviceQueue, o driver passa um ponteiro para o armazenamento que fornece para o objeto de fila do dispositivo.
Depois de iniciar seus dispositivos, o driver pode inserir um IRP em sua fila de dispositivos chamando KeInsertDeviceQueue, que coloca o IRP na parte final da fila, ou KeInsertByKeyDeviceQueue, que coloca o IRP na fila de acordo com um valor SortKey determinado pelo driver, conforme mostrado na figura anterior.
Cada uma dessas rotinas de suporte retorna um valor booliano que indica se o IRP foi inserido na fila. Cada uma dessas chamadas também define o estado do objeto de fila do dispositivo como Ocupado se a fila estiver vazia no momento (Não Ocupado). No entanto, se a fila estiver vazia (Não Ocupada), nem a rotina De DeviceQueue do KeInsertXxx insere o IRP na fila. Em vez disso, ele define o estado do objeto de fila do dispositivo como Ocupado e retorna FALSE. Como o IRP não foi enfileirado, o driver deve passá-lo para outra rotina de driver para processamento adicional.
Ao configurar filas de dispositivo suplementares, siga esta diretriz de implementação:
Quando uma chamada para KeInsertXxxDeviceQueue retorna FALSE, o chamador deve passar o IRP em que tentou fazer fila para processamento adicional para outra rotina de driver. No entanto, a chamada para KeInsertXxxDeviceQueue altera o estado do objeto de fila do dispositivo para Ocupado, portanto, o próximo IRP a entrar é inserido na fila, a menos que o driver chame KeRemoveXxxDeviceQueue primeiro.
Quando o estado do objeto da fila do dispositivo é definido como Ocupado, o driver pode desempacotar um IRP para processamento adicional ou redefinir o estado para Not-Busy chamando uma das seguintes rotinas de suporte:
KeRemoveDeviceQueue para remover o IRP no cabeçalho da fila
KeRemoveByKeyDeviceQueue para remover um IRP escolhido de acordo com um valor SortKey determinado pelo driver
KeRemoveEntryDeviceQueue para remover um IRP específico na fila ou para determinar se um IRP específico está na fila
KeRemoveEntryDeviceQueue retorna um Boolean indicando se o IRP estava na fila do dispositivo.
Chamar qualquer uma dessas rotinas para remover uma entrada de uma fila de dispositivos vazia, mas Ocupado altera o estado da fila para Não Ocupado.
Cada objeto de fila de dispositivo é protegido por um bloqueio de rotação executivo interno (não mostrado na figura Usando um objeto de fila de dispositivo ). Como resultado, um driver pode inserir IRPs na fila e removê-los de maneira segura de vários processadores de qualquer rotina de driver em execução em menos de ou igual a IRQL = DISPATCH_LEVEL. Devido a essa restrição irql, um driver não pode chamar qualquer rotina KeXxxDeviceQueue de suas rotinas ISR ou SynchCritSection , que são executadas em DIRQL.
Consulte Gerenciando prioridades de hardware e bloqueios de rotação para obter mais informações. Para requisitos de IRQL para uma rotina de suporte específica, consulte a página de referência da rotina.