Partilhar via


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

A opção Forçar solicitações de E/S pendentes retorna aleatoriamente o STATUS_PENDING em resposta às chamadas de um driver para IoCallDriver. Esta opção testa a lógica do driver para responder aos valores de retorno STATUS_PENDING de IoCallDriver.

Esta opção é suportada apenas no Windows Vista e em versões posteriores do sistema operativo Windows.

Atenção Não use esta opção num driver a menos que tenha conhecimento detalhado da operação do driver e tenha verificado que o driver foi projetado para lidar com valores de retorno STATUS_PENDING 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ções de memória e comportamento incomum do sistema que pode ser difícil de depurar ou corrigir.

Por que obrigar solicitações pendentes de E/S?

Drivers de nível superior numa stack de drivers chamam IoCallDriver para passar um IRP para drivers de nível inferior na stack de drivers. A rotina de despacho do condutor no controlador de nível inferior que recebe o IRP pode completar o IRP imediatamente ou retornar STATUS_PENDING e concluir o IRP no instante posterior.

Normalmente, o chamador deve estar preparado para lidar com qualquer um dos resultados. No entanto, como a maioria das rotinas de despacho lida com o IRP imediatamente, a lógica STATUS_PENDING no chamador não é frequentemente utilizada, e erros graves de lógica podem não ser detetados. A opção Forçar solicitações de E/S pendentes interceta 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 este teste, reveja o design do driver e o código-fonte e confirme que o driver está preparado para lidar com STATUS_PENDING em todas as suas chamadas IoCallDriver.

Muitos drivers não são projetados para lidar com STATUS_PENDING em todas as chamadas para IoCallDriver. Eles podem estar enviando o IRP para um driver específico e conhecido que tem a garantia de completar 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 motoristas devem lidar com STATUS_PENDING?

O driver de nível superior que chama IoCallDriver deve manipular um valor de retorno 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 deve aguardar pela conclusão do IRP ao chamar KeWaitForSingleObject no evento especificado.

  • O driver deve antecipar que o IRP pode ser libertado antes que o Gestor de I/O sinalize o evento.

  • Depois de chamar IoCallDriver, o chamador não pode fazer referência ao IRP.

Quais erros são detetados pela solicitação de E/S pendente?

A opção Force Pending I/O Request deteta os seguintes erros no driver que chama IoCallDriver e recebe um valor de retorno 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 pode 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 libertado, o controlador falhará.

  • O driver chama incorretamente uma função relacionada. 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 motorista espera pelo 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 na aplicação dos caminhos de código STATUS_PENDING em drivers verificados. Em versões anteriores do Windows, o Verificador de Drivers forçava que a conclusão de um IRP fosse atrasada somente quando a primeira IoCompleteRequest para esse IRP era executada. Isso significa que a eficácia da verificação de Driver1 pode ser reduzida pelo comportamento de Driver2 da mesma pilha de dispositivos. O Driver2 pode aguardar a conclusão de forma síncrona antes de retornar de sua rotina de despacho para o Driver1. O atraso forçado da conclusão do IRP ocorre precisamente antes que a solicitação de E/S volte para o 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.

#B0 #A1 Ativar Esta Opção

Para ativar Forçar solicitações de E/S pendentes, 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 Verificadores de Driver ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionando Opções do Verificador de Controladores.

A opção Forçar solicitações de E/S pendentes é suportada 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 a 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 tentar ativar apenas Forçar Solicitações de E/S Pendentes (verificador /sinalizadores 0x200), o Verificador de Driver habilitará automaticamente tanto Forçar Solicitações de E/S Pendentes (0x200) como a Verificação de E/S.

    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 entra em vigor imediatamente, mas é perdida quando você desliga ou reinicia o computador. Para obter detalhes, consulte Usando Configuração Volátil.

  • Usando o Gestor do Verificador de Drivers

    1. Inicie o Driver Verifier Manager. Digite Verifier numa janela da Linha de Comandos.
    2. Selecione Criar configurações personalizadas (para desenvolvedores de código) e clique em Avançar.
    3. Selecione configurações individuais de uma lista completa.
    4. Selecione Verificação de E/S e force solicitações de E/S pendentes.

    Se selecionar apenas Forçar solicitações de E/S pendentes, o Driver Verifier Manager lembrará que a verificação de E/S é necessária e oferecerá ativá-la para si.

Visualizando os resultados

Para exibir os resultados do teste Force Pending I/O Requests, 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 Debugging Tools for Windows .

Se a máquina de teste falhar como resultado do teste Force Pending I/O Requests, 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 seu driver. Por exemplo, se utilizares o comando kP, que exibe o quadro de pilha para uma thread, poderás encontrar o endereço IRP entre os parâmetros de função do rastreio de pilha atual. Em seguida, execute !verifier 40 e procure o endereço do IRP. Os rastreamentos de pilha de força pendente mais recentes aparecem na parte superior da tela.

Por exemplo, o seguinte stack trace de Pci.sys mostra a sua resposta a Forçar Pedidos de I/O Pendentes. O teste não revela quaisquer erros na lógica 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 traço da pilha mostra que Acpi.sys estava a tentar concluir o IRP 8f84ef00. Driver Verifier forçou uma conclusão diferida, então Acpi.sys retornou STATUS_PENDING para pci!PciCallDownIrpStack. Se esta chamada tivesse causado uma falha, o proprietário do driver precisaria rever o código-fonte para pci! PciCallDownIrpStack e revisá-lo para lidar com o STATUS_PENDING corretamente.