Forçar solicitações de E/S pendentes

A opção Forçar Solicitações de E/S Pendentes retorna aleatoriamente STATUS_PENDING em resposta às chamadas de um driver para IoCallDriver. Essa opção testa a lógica do driver para responder a STATUS_PENDING valores retornados de IoCallDriver.

Essa opção tem suporte apenas no Windows Vista e em versões posteriores do sistema operacional Windows.

Cuidado Não use essa opção em um driver, a menos que você tenha conhecimento detalhado da operação do driver e tenha verificado que o driver foi projetado para lidar com STATUS_PENDING retornar valores de todas as suas chamadas para IoCallDriver. Executar essa opção em um driver que não foi projetado para lidar com STATUS_PENDING de todas as chamadas pode resultar em falhas, corrupção de memória e comportamento incomum do sistema que pode ser difícil de depurar ou corrigir.

Por que usar forçar solicitações de E/S pendentes?

Drivers de nível superior em uma pilha de driver chamam IoCallDriver para passar um IRP para baixo para drivers de nível inferior na pilha de driver. A rotina de expedição do driver no driver de nível inferior que recebe o IRP pode concluir o IRP imediatamente ou retornar STATUS_PENDING e concluir o IRP posteriormente.

Normalmente, o chamador deve estar preparado para lidar com qualquer resultado. No entanto, como a maioria das rotinas de expedição lida com o IRP imediatamente, a lógica de STATUS_PENDING no chamador não é frequentemente exercida e erros lógicos graves podem não ser detectados. A opção Forçar Solicitações de E/S Pendente intercepta chamadas para IoCallDriver e retorna STATUS_PENDING para testar a lógica usada com pouca frequência do driver de chamada.

Quando você usa Forçar Solicitações de E/S Pendentes?

Antes de executar esse teste, examine o design do driver e o código-fonte e confirme se o driver se destina a lidar com STATUS_PENDING de todas as chamadas do IoCallDriver .

Muitos drivers não foram projetados para lidar com STATUS_PENDING em todas as chamadas para IoCallDriver. Eles podem estar enviando o IRP para um driver conhecido específico que tem a garantia de concluir o IRP imediatamente. Enviar STATUS_PENDING para um driver que não o manipula pode causar falhas de driver e sistema e corrupção de memória.

Como os drivers devem lidar com STATUS_PENDING?

O driver de nível superior que chama IoCallDriver deve lidar com um valor retornado STATUS_PENDING da seguinte maneira:

  • Antes de chamar IoCallDriver, o driver deve chamar IoBuildSynchronousFsdRequest para organizar o processamento síncrono do IRP.

  • Se IoCallDriver retornar STATUS_PENDING, o driver deverá aguardar a conclusão do IRP chamando KeWaitForSingleObject no evento especificado.

  • O driver deve prever que o IRP possa ser liberado antes que o Gerenciador de E/S sinalize o evento.

  • Depois de chamar IoCallDriver, o chamador não pode referenciar o IRP.

Quais erros força a detecção de solicitação de E/S pendente?

A opção Forçar Solicitação de E/S Pendente detecta os seguintes erros no driver que chama IoCallDriver e recebe um valor retornado STATUS_PENDING:

  • O driver não chama IoBuildSynchronousFsdRequest para organizar o processamento síncrono.

  • O driver não chama KeWaitForSingleObject.

  • O driver faz referência a um valor na estrutura IRP depois de chamar IoCallDriver. Depois de chamar IoCallDriver, o driver de nível superior não poderá acessar o IRP, a menos que tenha definido uma rotina de conclusão e, em seguida, somente quando todos os drivers de nível inferior tiverem concluído o IRP. Se o IRP for liberado, o driver falhará.

  • O driver chama uma função relacionada incorretamente. Por exemplo, o driver chama KeWaitForSingleObject e passa um identificador para o evento (como o parâmetro Object ), em vez de passar um ponteiro para um objeto de evento.

  • O driver aguarda o evento errado. Por exemplo, o driver chama IoSetCompletionRoutine, mas aguarda um evento interno que é sinalizado por sua própria rotina de conclusão, em vez de aguardar o evento IRP que é sinalizado pelo Gerenciador de E/S quando o IRP é concluído.

Forçar alterações de solicitações de E/S pendentes introduzidas no Windows 7

A partir do Windows 7, a opção Forçar Solicitações de E/S Pendentes é mais eficaz em forçar o exercício dos caminhos de código STATUS_PENDING em drivers verificados. Em versões anteriores do Windows, o Verificador de Driver forçou uma conclusão de IRP a ser atrasada somente quando o primeiro IoCompleteRequest para esse IRP for executado. Isso significa que a eficácia da verificação do Driver1 pode ser reduzida pelo comportamento do Driver2 da mesma pilha de dispositivos. O Driver2 pode aguardar de forma síncrona para a conclusão antes de retornar de sua rotina de expedição para Driver1. O atraso forçado da conclusão do IRP ocorre precisamente antes que a solicitação de E/S seja desenrolada novamente no driver verificado no caminho de conclusão. Isso significa que o caminho de código STATUS_PENDING do driver verificado é realmente exercido e o driver verificado percebe um atraso na conclusão.

Ativando essa opção

Para ativar o Force Pending E/S Requests, você também deve ativar a Verificação de E/S. Você pode ativar a opção Forçar Solicitações de E/S Pendentes para um ou mais drivers usando o Gerenciador de Verificador de Driver ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionando opções do verificador de driver.

A opção Forçar Solicitações de E/S Pendentes tem suporte apenas no Windows Vista e em versões posteriores do Windows.

  • Na linha de comando

    Para ativar Forçar Solicitações de E/S Pendentes, use um valor de sinalizador de 0x210 ou adicione 0x210 ao valor do sinalizador. Esse valor ativa a Verificação de E/S (0x10) e força solicitações de E/S pendentes (0x200).

    Por exemplo:

    verifier /flags 0x210 /driver MyDriver.sys
    

    A opção estará ativa após a próxima inicialização.

    Se você tentar ativar apenas solicitações de E/S pendentes (verificadores /sinalizadores 0x200), o Verificador de Driver habilitará automaticamente as Solicitações de E/S Pendentes (0x200) e a Verificação de E/S pendentes.

    Você também pode ativar e desativar Solicitações de E/S Pendentes de Força sem reinicializar o computador adicionando o parâmetro /volatile ao comando . Por exemplo:

    verifier /volatile /flags 0x210 /adddriver MyDriver.sys
    

    Essa configuração é efetiva imediatamente, mas é perdida quando você desliga ou reinicializa o computador. Para obter detalhes, consulte Usando configurações voláteis.

  • Usando o Gerenciador de Verificador de Driver

    1. Iniciar o Gerenciador de Verificador de Driver. Digite Verificador em uma janela do Prompt de Comando.
    2. Selecione Criar configurações personalizadas (para desenvolvedores de código) e clique em Avançar.
    3. Selecione Selecionar configurações individuais em uma lista completa.
    4. Selecione Verificação de E/S e force solicitações de E/S pendentes.

    Se você selecionar apenas Forçar Solicitações de E/S Pendentes, o Gerenciador de Verificador de Driver lembrará que a Verificação de E/S é necessária e oferece para habilitá-la para você.

Exibindo os resultados

Para exibir os resultados do teste Forçar Solicitações de E/S Pendentes, use a extensão do depurador !verifier com um valor de sinalizador de 0x40.

Para obter informações sobre !verifier, consulte o tópico !verifier na documentação Ferramentas de Depuração para Windows .

Se o computador de teste falhar como resultado do teste Forçar Solicitações de E/S Pendentes, você poderá usar o comando !verifier 40 para encontrar a causa. Em um rastreamento de pilha atual, localize o endereço do IRP que foi usado recentemente pelo driver. Por exemplo, se você usar o comando kP , que exibe o quadro de pilha de um thread, poderá encontrar o endereço IRP entre os parâmetros de função do rastreamento de pilha atual. Em seguida, execute !verifier 40 e procure o endereço do IRP. Os rastreamentos de pilha pendentes de força mais recentes aparecem na parte superior da tela.

Por exemplo, o seguinte rastreamento de pilha de Pci.sys mostra sua resposta a Forçar Solicitações de E/S Pendentes. O teste não revela erros na lógica de Pci.sys.

kd> !verifier 40
# Size of the log is 0x40
========================================================
IRP: 8f84ef00 - forced pending from stack trace:

     817b21e4 nt!IovpLocalCompletionRoutine+0xb2
     81422478 nt!IopfCompleteRequest+0x15c
     817b2838 nt!IovCompleteRequest+0x9c
     84d747df acpi!ACPIBusIrpDeviceUsageNotification+0xf5
     84d2d36c acpi!ACPIDispatchIrp+0xe8
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     817c6a9d nt!ViFilterDispatchPnp+0xe9
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84fed489 pci!PciCallDownIrpStack+0xbf
     84fde1cb pci!PciDispatchPnpPower+0xdf
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     817c6a9d nt!ViFilterDispatchPnp+0xe9
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84ff2ff5 pci!PciSendPnpIrp+0xbd
 84fec820 pci!PciDevice_DeviceUsageNotification+0x6e
     84fde1f8 pci!PciDispatchPnpPower+0x10c
 817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84d76ce2 acpi!ACPIFilterIrpDeviceUsageNotification+0x96
     84d2d36c acpi!ACPIDispatchIrp+0xe8
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c
     84f7f16c PCIIDEX!PortWdmForwardIrpSynchronous+0x8e
     84f7b2b3 PCIIDEX!GenPnpFdoUsageNotification+0xcb
     84f7d301 PCIIDEX!PciIdeDispatchPnp+0x45
     817b258f nt!IovCallDriver+0x19d
     8142218e nt!IofCallDriver+0x1c

O rastreamento de pilha mostra que Acpi.sys estava tentando concluir IRP 8f84ef00. O Verificador de Driver forçou uma conclusão adiada, então Acpi.sys retornou STATUS_PENDING para pci! PciCallDownIrpStack. Se essa chamada tivesse causado uma falha, o proprietário do driver precisaria examinar o código-fonte para pci! PciCallDownIrpStack e revise-o para lidar com o STATUS_PENDING corretamente.