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
- Iniciar o Gerenciador de Verificador de Driver. Digite Verificador em uma janela do Prompt de Comando.
- Selecione Criar configurações personalizadas (para desenvolvedores de código) e clique em Avançar.
- Selecione Selecionar configurações individuais em uma lista completa.
- 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.