Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Novos drivers devem usar a estrutura de fila IRP segura para cancelamento em preferência aos métodos descritos nesta seção.
Como o driver do controlador de disquete do sistema, um driver com uma thread dedicada ao dispositivo, em vez de uma rotina StartIo, geralmente gere a sua própria fila de IRPs numa fila interbloqueada duplamente ligada. O thread do driver puxa IRPs de sua fila intertravada quando há trabalho a ser feito no dispositivo.
Em geral, o driver deve gerenciar a sincronização com seu thread para quaisquer recursos compartilhados entre o thread e outras rotinas de driver. O driver também deve ter alguma maneira de notificar seu thread criado pelo driver de que os IRPs estão na fila. Normalmente, o thread aguarda em um objeto dispatcher, armazenado na extensão do dispositivo, até que as rotinas Dispatch do driver definam o objeto dispatcher para o estado Signaled depois de inserir um IRP na fila intertravada.
Quando as rotinas de despacho do driver são chamadas, cada uma verifica os parâmetros na posição da stack de E/S da entrada do IRP e, se forem válidos, enfileira a solicitação para processamento posterior. Para cada IRP enfileirado para uma thread dedicada ao driver, a rotina de despacho deve configurar qualquer contexto que sua thread precise para processar este IRP antes de invocar ExInterlockedInsertXxxList. O local da pilha de E/S do driver em cada IRP dá ao thread do driver acesso à extensão de dispositivo do objeto de dispositivo de destino, onde o driver pode compartilhar informações de contexto com seu thread, pois o thread remove cada IRP da fila.
Um driver que enfileira IRPs canceláveis deve implementar uma rotina Cancelar. Como os IRPs são cancelados de forma assíncrona, você deve garantir que seu motorista evite as condições de corrida que podem resultar. Consulte Sincronizar o cancelamento de IRP Para mais informações sobre situações de disputa associadas ao cancelamento de IRPs e técnicas para evitá-las.
Qualquer thread criado pelo driver é executado em IRQL = PASSIVE_LEVEL e em uma prioridade de tempo de execução base definida anteriormente quando o driver chamou PsCreateSystemThread. A chamada do thread para ExInterlockedRemoveHeadList aumenta temporariamente o IRQL para DISPATCH_LEVEL no processador atual enquanto o IRP está sendo removido da fila interna do driver. O IRQL original é restaurado para PASSIVE_LEVEL no retorno desta chamada.
Qualquer thread de driver (ou retorno de chamada de thread de trabalho fornecido pelo driver) deve gerenciar cuidadosamente os IRQLs nos quais ele é executado. Por exemplo, considere o seguinte:
Como os threads do sistema geralmente são executados em IRQL = PASSIVE_LEVEL, é possível que um thread de driver aguarde que os objetos dispatcher definidos pelo kernel sejam definidos para o estado sinalizado.
Por exemplo, um thread dedicado ao dispositivo pode esperar que outros drivers satisfaçam um evento e concluam algum número de IRPs de transferência parcial que o thread configura com IoBuildSynchronousFsdRequest.
No entanto, essa linha de execução dedicada ao dispositivo deve aumentar o IRQL no processador atual antes de chamar certas rotinas de suporte.
Por exemplo, se um driver usa DMA, o seu thread dedicado ao dispositivo deve aninhar as suas chamadas para AllocateAdapterChannel e FreeAdapterChannel entre chamadas para KeRaiseIrql e KeLowerIrql porque estas rotinas e certas outras rotinas de suporte para operações de DMA devem ser chamadas com IRQL = DISPATCH_LEVEL.
Lembre-se de que rotinas de StartIo são executadas em DISPATCH_LEVEL, portanto, os motoristas que usam DMA não precisam fazer chamadas para as rotinas de KeXxxIrql de suas rotinas StartIo.
Um thread criado por driver pode acessar a memória paginável porque é executado em um contexto de thread não arbitrário (próprio) em IRQL = PASSIVE_LEVEL, mas muitas outras rotinas de driver padrão são executadas em IRQL >= DISPATCH_LEVEL. Se um thread criado por driver aloca memória que pode ser acessada por essa rotina, ele deve alocar a memória do pool não paginado. Por exemplo, se uma sequência dedicada ao dispositivo aloca qualquer buffer que será acessado posteriormente pelo ISR do driver ou SynchCritSection, AdapterControl, AdapterListControl, ControllerControl, DpcForIsr, CustomDpc, IoTimer, CustomTimerDpc, ou, num driver de nível superior, IoCompletion routine, a memória alocada pela sequência não pode ser paginável.
Se o driver mantiver informações de estado partilhadas ou recursos numa extensão de dispositivo, um thread do driver (como uma rotina StartIo) deverá sincronizar o seu acesso a um dispositivo físico e aos dados partilhados com as outras rotinas do driver que acedem ao mesmo dispositivo, localização de memória ou recursos.
Se o thread compartilhar o dispositivo ou o estado com o ISR, ele deverá usar KeSynchronizeExecution para chamar uma rotina deSynchCritSectionfornecida pelo driver para programar o dispositivo ou acessar o estado compartilhado. Consulte Utilização de secções críticas.
Se o thread compartilhar estado ou recursos com rotinas diferentes do ISR, o driver deve proteger os recursos ou o estado partilhado com um "executive spin lock" inicializado e gerido pelo driver, para o qual o driver fornece armazenamento. Para obter mais informações, consulte Spin Locks.
Para obter mais informações sobre as compensações de design de usar um thread de driver para um dispositivo lento, consulte Polling a Device. Consulte também Gerenciando prioridades de hardware. Para obter informações específicas sobre IRQLs para rotinas de suporte específicas, consulte a página de referência da rotina.