Partilhar via


Usando Objetos Temporizadores

A figura a seguir ilustra o uso de um temporizador de notificação para configurar um intervalo de tempo limite para uma operação e, em seguida, aguardar enquanto outras rotinas de driver processam uma solicitação de E/S.

diagrama ilustrando a espera por um objeto temporizador.

Como mostra a figura anterior, um driver deve fornecer armazenamento para o objeto de temporizador, que deve ser inicializado por uma chamada para KeInitializeTimer com um ponteiro para esse armazenamento. Um driver normalmente faz essa chamada de sua rotina AddDevice .

No contexto de um encadeamento específico, como um encadeamento criado por um driver ou um encadeamento que solicita uma operação de E/S síncrona, o driver pode aguardar pelo seu objeto de temporizador, conforme mostrado na figura anterior.

  1. O thread chama KeSetTimer com um ponteiro para o objeto temporizador e um determinado valor DueTime , expresso em unidades de 100 nanossegundos. Um valor positivo para DueTime especifica um tempo absoluto no qual o objeto do temporizador deve ser removido da fila de temporizadores do kernel e definido para o estado Signaled. Um valor negativo para DueTime especifica um intervalo relativo à hora atual do sistema.

    Observe que a thread (ou a rotina do driver em execução num thread do sistema) passa um ponteiro NULL para o objeto DPC (mostrado anteriormente na figura que ilustra o uso de objetos temporizador e DPC para uma rotina CustomTimerDpc) quando chama KeSetTimer se estiver a esperar no objeto temporizador em vez de colocar em fila uma rotina CustomTimerDpc.

  2. O thread chama KeWaitForSingleObject com um ponteiro para o objeto timer, que coloca o thread em um estado de espera enquanto o objeto timer está na fila de timer do kernel.

  3. O DueTime dado expira.

  4. O kernel remove o objeto do temporizador da fila, define-o para o estado Assinalado e altera o estado do thread de espera para pronto.

  5. O kernel despacha o thread para execução assim que um processador está disponível: ou seja, nenhum outro thread com uma prioridade mais alta está atualmente no estado pronto e não há rotinas de modo kernel para serem executadas em um IRQL mais alto.

As rotinas de driver executadas em IRQL >= DISPATCH_LEVEL podem causar o esgotamento do tempo das solicitações utilizando um objeto de temporizador com um objeto DPC associado para enfileirar uma rotina CustomTimerDpc fornecida pelo driver. Somente as rotinas de driver que são executadas num contexto de thread não arbitrário podem esperar por um intervalo não-nulo num objeto de temporizador, conforme mostrado na figura anterior.

Como qualquer outro thread, um thread criado por driver é representado por um objeto de thread do kernel, que também é um objeto dispatcher. Consequentemente, um driver não precisa que a sua thread criada pelo driver utilize um objeto temporizador para se colocar voluntariamente em estado de espera por um intervalo específico. Em vez disso, o thread pode chamar KeDelayExecutionThread com um intervalo fornecido pelo chamador. Para obter mais informações sobre essa técnica, consulte Sondagem de um dispositivo.

As rotinas DriverEntry, Reinitialize e Unload também são executadas em um contexto de thread do sistema, para que os drivers possam chamar KeWaitForSingleObject com um objeto de timer inicializado pelo driver ou KeDelayExecutionThread enquanto estão inicializando ou descarregando. Um driver de dispositivo pode chamar KeStallExecutionProcessor por um intervalo muito curto (de preferência algo inferior a 50 microssegundos) se precisar esperar que o dispositivo atualize o estado durante sua inicialização.

No entanto, os drivers de nível superior geralmente usam outro mecanismo de sincronização em suas rotinas DriverEntry e Reinitialize em vez de usar um objeto de temporizador. Os drivers de nível superior devem ser sempre projetados para se sobrepor a qualquer driver de nível inferior de um determinado tipo ou tipo de dispositivo. Portanto, um driver de nível mais alto tende a tornar-se lento para carregar se aguarda por um objeto de temporizador ou chama KeDelayExecutionThread porque este driver deve esperar por um intervalo longo o suficiente para acomodar o dispositivo mais lento possível que o suporta. Note também que um intervalo "seguro", mas mínimo, para tal espera é muito difícil de determinar.

Da mesma forma, os drivers PnP não devem esperar que outras ações ocorram, mas devem usar o mecanismo de notificação do gerenciador PnP.