Partilhar via


Diretrizes para escrever rotinas de DPC

Tenha em mente os seguintes pontos ao escrever uma rotina DpcForIsr ou CustomDpc :

  • Uma rotina DpcForIsr ou CustomDpc deve sincronizar seu acesso a um dispositivo físico e a quaisquer informações de estado compartilhadas ou recursos que o driver mantém, com outras rotinas do driver que acessam o mesmo dispositivo ou locais de memória.

    Se uma rotina DpcForIsr ou CustomDpc compartilhar o dispositivo ou estado com um ISR, ele deverá chamar KeSynchronizeExecution, fornecendo o endereço de uma rotina SynchCritSection fornecida pelo driver que programa o dispositivo ou acessa o estado compartilhado. Para obter mais informações, consulte Usando Seções Críticas.

    Se uma rotina DpcForIsr ou CustomDpc compartilhar estados ou recursos, como uma fila intertravada ou um objeto de temporizador, com rotinas diferentes de um ISR, ela deverá proteger os estados ou recursos compartilhados com um bloqueio de spin executivo inicializado pelo driver. Para obter mais informações, consulte Spin Locks.

  • As rotinas DpcForIsr e CustomDpc são executadas em IRQL = DISPATCH_LEVEL, o que restringe o conjunto de rotinas de suporte que podem ser chamadas.

    Por exemplo, as rotinas DpcForIsr e CustomDpc não podem acessar nem alocar memória paginável e não podem esperar que os objetos dispatcher do kernel sejam definidos para o estado sinalizado. Por outro lado, eles podem adquirir e liberar um bloqueio de rotação executivo do driver com KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel, que funcionam mais rápido do que KeAcquireSpinLock e KeReleaseSpinLock.

    Embora uma rotina DPC não possa fazer chamadas de bloqueio, ela pode enfileirar um item de trabalho para ser executado num subprocesso de trabalho do sistema que é executado em IRQL igual a PASSIVE_LEVEL. O item de trabalho pode fazer chamadas de bloqueio que aguardam objetos do dispatcher. Para enfileirar um item de trabalho, uma rotina DpcForIsr normalmente chama uma rotina como IoQueueWorkItem, e uma rotina CustomDpc normalmente chama a rotina ExQueueWorkItem .

  • As rotinas DpcForIsr e CustomDpc são normalmente responsáveis por iniciar a próxima operação de E/S no dispositivo.

    Para drivers de dispositivo físico de nível mais baixo que usam E/S direta, essa responsabilidade pode incluir o uso de uma rotina SynchCritSection para programar o dispositivo para transferir mais dados a fim de satisfazer o IRP atual antes que o driver chame IoStartNextPacket.

  • As rotinas DpcForIsr e CustomDpc devem ser executadas apenas por breves períodos e devem delegar o máximo de processamento possível aos threads de trabalho.

    Enquanto uma rotina DPC é executada em um processador, todos os threads são impedidos de serem executados no mesmo processador. Outras rotinas de DPC que estão enfileiradas e prontas para execução podem ser bloqueadas de execução até que a rotina atual do DPC seja concluída. Para evitar a degradação da capacidade de resposta do sistema, uma rotina típica de DPC não deve ser executada por mais de 100 microssegundos cada vez que é chamada. Se uma tarefa requer mais de 100 microssegundos e deve ser executada em IRQL igual a DISPATCH_LEVEL, a rotina DPC deve terminar após 100 microssegundos e agendar uma ou mais rotinas CustomTimerDpc para concluir a tarefa posteriormente. Para obter mais informações sobre rotinas CustomTimerDpc , consulte Timer Objects and DPCs.

    Uma rotina DPC deve executar apenas tarefas que devem ser executadas em DISPATCH_LEVEL e, em seguida, delegar qualquer trabalho restante relacionado a interrupções para threads que são executados em IRQL = PASSIVE_LEVEL. Por exemplo, uma rotina DPC pode enfileirar um item de trabalho para ser executado em um thread de trabalho do sistema.

    As rotinas DPC que chamam a rotina KeStallExecutionProcessor para atrasar a execução não devem especificar atrasos superiores a 100 microssegundos.

    Use as ferramentas de análise de desempenho no WDK para avaliar os tempos de execução das rotinas do DPC. Para obter um exemplo que usa a ferramenta Tracelog para monitorar os tempos de execução do DPC, consulte o Exemplo 15: Medindo o tempo do DPC/ISR.

  • Se o driver usa DMA e sua rotina AdapterControl retorna KeepObject ou DeallocateObjectKeepRegisters (mantendo assim o canal do controlador DMA do sistema ou o adaptador bus-master para operações de transferência adicionais), a rotina DpcForIsr ou CustomDpc é responsável por liberar o objeto do adaptador ou os registros de mapa com FreeAdapterChannel ou FreeMapRegisters antes de concluir o IRP atual e retornar o controle.

  • Se um driver de dispositivo físico de nível mais baixo configurar um objeto de controlador para sincronizar operações de E/S através do controlador para dispositivos conectados, sua rotina DpcForIsr ou CustomDpc é responsável por liberar o objeto de controlador usando IoFreeController antes de concluir o IRP atual e retornar o controle.

  • As rotinas DpcForIsr e CustomDpc geralmente são responsáveis por registrar quaisquer erros de dispositivo que ocorreram durante o processamento de uma determinada solicitação, tentar novamente a solicitação atual, se necessário e possível, e por definir o bloco de status de E/S e chamar IoCompleteRequest para o IRP atual.

  • Se o driver e o dispositivo suportarem operações de E/S sobrepostas, o driver deverá seguir as regras para lidar com operações de E/S sobrepostas.

  • A rotina DpcForIsr ou CustomDpc de qualquer driver geralmente conclui o processamento de E/S apenas para um subconjunto dos códigos de controle de E/S públicos que o driver deve suportar. Em particular, a rotina DPC conclui operações para solicitações de controle de dispositivos com as seguintes características:

    • Solicitações que alteram o estado do dispositivo físico

    • Solicitações que exigem o retorno de informações inerentemente voláteis sobre o dispositivo físico