Compartilhar via


Escrevendo um ISR

Os drivers para dispositivos físicos que geram interrupções devem ter pelo menos uma ISR (rotina de serviço de interrupção). O ISR deve fazer o que for apropriado para o dispositivo para ignorar a interrupção, possivelmente incluindo impedir que o dispositivo interrompa. Em seguida, ele deve fazer apenas o que é necessário para salvar o estado e enfileirar um DPC para concluir a operação de E/S com uma prioridade mais baixa (IRQL) do que aquela em que o ISR é executado.

O ISR de um driver é executado em um contexto de interrupção, em algum DIRQL atribuído pelo sistema, conforme especificado pelo parâmetro SynchronizeIrql para IoConnectInterruptEx.

ISRs são interrompíveis. Outro dispositivo com um DIRQL mais alto atribuído pelo sistema pode interromper ou uma interrupção de sistema DE ALTA IRQL pode ocorrer a qualquer momento.

Antes que o sistema chame um ISR, ele adquire o bloqueio de rotação da interrupção para que o ISR não possa ser executado simultaneamente em outro processador. Depois que o ISR retorna, o sistema libera o bloqueio de rotação.

Como um ISR é executado em um IRQL relativamente alto, que mascara interrupções com um IRQL equivalente ou inferior no processador atual, ele deve retornar o controle o mais rápido possível. Além disso, a execução de um ISR no DIRQL restringe o conjunto de rotinas de suporte que o ISR pode chamar. Para obter mais informações, consulte Gerenciando prioridades de hardware.

Normalmente, um ISR executa as seguintes etapas gerais:

  • Se o dispositivo que causou a interrupção não for compatível com o ISR, o ISR retornará FALSE imediatamente.

  • Caso contrário, o ISR limpa a interrupção, se necessário, salvando qualquer contexto de dispositivo necessário e enfileira um DPC para concluir a operação de E/S em um IRQL inferior. Consulte DPC Objects and DPCs (Objetos DPC e DPCs ) para obter mais informações. O ISR deve retornar TRUE.

Especificamente, em drivers que não se sobrepõem às operações de E/S do dispositivo, o ISR deve fazer o seguinte:

  1. Determine se a interrupção é espúria. Nesse caso, retorne FALSE imediatamente para que o ISR do dispositivo interrompido seja chamado imediatamente. Caso contrário, continue o processamento de interrupção.

  2. Interrompa a interrupção do dispositivo, se necessário.

  3. Coletar quaisquer informações de contexto que a rotina DpcForIsr (ou CustomDpc) precisará para concluir o processamento de E/S para a operação atual.

  4. Armazene esse contexto em uma área acessível para a rotina DpcForIsr ou CustomDpc , geralmente na extensão de dispositivo do objeto de dispositivo de destino para o qual o processamento da solicitação de E/S atual causou a interrupção.

    Se um driver se sobrepõe a operações de E/S, as informações de contexto devem incluir uma contagem de solicitações pendentes que a rotina DPC precisa concluir, juntamente com qualquer contexto que a rotina DPC precise para concluir cada solicitação. Se o ISR for chamado para lidar com outra interrupção antes da execução do DPC, ele não deverá substituir o contexto salvo para uma solicitação que ainda não foi concluída pelo DPC.

  5. Se o driver tiver uma rotina DpcForIsr , chame IoRequestDpc com ponteiros para o IRP atual, o objeto de dispositivo de destino e o contexto salvo. IoRequestDpc enfileira a rotina DpcForIsr a ser executada assim que o IRQL fica abaixo DISPATCH_LEVEL em um processador.

    Se o driver tiver uma rotina CustomDpc , chame KeInsertQueueDpc com um ponteiro para o objeto DPC (associado à rotina CustomDpc ) e ponteiros para qualquer contexto salvo que a rotina CustomDpc precisará para concluir a operação. Normalmente, o ISR também passa ponteiros para o IRP atual e o objeto de dispositivo de destino. A rotina CustomDpc é executada assim que o IRQL fica abaixo DISPATCH_LEVEL em um processador.

  6. Retornar TRUE para indicar que seu dispositivo gerou a interrupção.

Em geral, um ISR não faz nenhum processamento de E/S real para atender a um IRP. Em vez disso, ele impede que seu dispositivo interrompa, configure as informações de estado necessárias e enfileira o DpcForIsr ou CustomDpc do driver para fazer qualquer processamento de E/S necessário para atender à solicitação atual que causou a interrupção do dispositivo.

Um ISR deve ser executado em DIRQL para o intervalo mais curto possível. Seguir esta diretriz aumenta a taxa de transferência de E/S para cada dispositivo no computador porque a execução em DIRQL mascara todas as interrupções às quais o sistema atribuiu um valor IRQL menor ou igual.

O SynchronizeIrql dos objetos de interrupção do driver, especificado quando o driver chamado IoConnectInterrupt, determina o DIRQL no qual o ISR do driver é executado. Para obter mais informações, consulte Sincronizando o acesso aos dados do dispositivo.