Forzar solicitudes de E/S pendientes

La opción Forzar solicitudes de E/S pendientes devuelve aleatoriamente STATUS_PENDING en respuesta a las llamadas de un controlador a IoCallDriver. Esta opción prueba la lógica del controlador para responder a STATUS_PENDING valores devueltos de IoCallDriver.

Esta opción solo se admite en Windows Vista y versiones posteriores del sistema operativo Windows.

Precaución No use esta opción en un controlador a menos que tenga conocimientos detallados sobre el funcionamiento del controlador y haya comprobado que el controlador está diseñado para controlar STATUS_PENDING devolver valores de todas sus llamadas a IoCallDriver. La ejecución de esta opción en un controlador que no está diseñado para controlar STATUS_PENDING desde todas las llamadas puede provocar bloqueos, daños en la memoria y un comportamiento inusual del sistema que puede ser difícil de depurar o corregir.

¿Por qué usar solicitudes de E/S pendientes forzadas?

Los controladores de nivel superior de una pila de controladores llaman a IoCallDriver para pasar un IRP a controladores de nivel inferior en la pila de controladores. La rutina de distribución del controlador en el controlador de nivel inferior que recibe el IRP puede completar el IRP inmediatamente o devolver STATUS_PENDING y completar el IRP más adelante.

Normalmente, el autor de la llamada debe estar preparado para controlar cualquiera de los resultados. Sin embargo, dado que la mayoría de las rutinas de envío controlan el IRP inmediatamente, es posible que no se detecte la lógica de STATUS_PENDING en el autor de la llamada y que no se detecten errores lógicos graves. La opción Forzar solicitudes de E/S pendiente intercepta las llamadas a IoCallDriver y devuelve STATUS_PENDING para probar la lógica usada con poca frecuencia del controlador de llamada.

¿Cuándo usa Forzar solicitudes de E/S pendientes?

Antes de ejecutar esta prueba, revise el diseño del controlador y el código fuente y confirme que el controlador está diseñado para controlar STATUS_PENDING desde todas sus llamadas a IoCallDriver .

Muchos controladores no están diseñados para controlar STATUS_PENDING en todas las llamadas a IoCallDriver. Es posible que envíen el IRP a un determinado controlador conocido que se garantiza que complete el IRP inmediatamente. El envío de STATUS_PENDING a un controlador que no lo controla puede provocar bloqueos del controlador y del sistema y daños en la memoria.

¿Cómo deben controlar los controladores STATUS_PENDING?

El controlador de nivel superior que llama a IoCallDriver debe controlar un valor devuelto STATUS_PENDING de la siguiente manera:

  • Antes de llamar a IoCallDriver, el controlador debe llamar a IoBuildSynchronousFsdRequest para organizar el procesamiento sincrónico del IRP.

  • Si IoCallDriver devuelve STATUS_PENDING, el controlador debe esperar a que se complete el IRP llamando a KeWaitForSingleObject en el evento especificado.

  • El controlador debe prever que el IRP podría liberarse antes de que el Administrador de E/S señale el evento.

  • Después de llamar a IoCallDriver, el autor de la llamada no puede hacer referencia al IRP.

¿Qué errores fuerza la detección de solicitudes de E/S pendientes?

La opción Forzar solicitud de E/S pendiente detecta los siguientes errores en el controlador que llama a IoCallDriver y recibe un valor devuelto STATUS_PENDING:

  • El controlador no llama a IoBuildSynchronousFsdRequest para organizar el procesamiento sincrónico.

  • El controlador no llama a KeWaitForSingleObject.

  • El controlador hace referencia a un valor en la estructura IRP después de llamar a IoCallDriver. Después de llamar a IoCallDriver, el controlador de nivel superior no puede acceder al IRP a menos que haya establecido una rutina de finalización y, a continuación, solo cuando todos los controladores de nivel inferior hayan completado el IRP. Si el IRP está liberado, el controlador se bloqueará.

  • El controlador llama a una función relacionada incorrectamente. Por ejemplo, el controlador llama a KeWaitForSingleObject y pasa un identificador al evento (como el parámetro Object ), en lugar de pasar un puntero a un objeto de evento.

  • El controlador espera el evento incorrecto. Por ejemplo, el controlador llama a IoSetCompletionRoutine, pero espera un evento interno señalado por su propia rutina de finalización, en lugar de esperar al evento IRP señalado por el Administrador de E/S cuando se completa el IRP.

Forzar cambios en las solicitudes de E/S pendientes introducidas en Windows 7

A partir de Windows 7, la opción Forzar solicitudes de E/S pendientes es más eficaz al forzar el ejercicio de las rutas de acceso de código STATUS_PENDING en controladores comprobados. En versiones anteriores de Windows, el Comprobador de controladores obligó a que se retrasara una finalización de IRP solo cuando se ejecuta la primera instancia de IoCompleteRequest para ese IRP. Esto significa que la eficacia de comprobar Driver1 se puede reducir mediante el comportamiento de Driver2 de la misma pila de dispositivos. Driver2 puede esperar sincrónicamente para la finalización antes de que vuelva de su rutina de envío a Driver1. El retraso forzado de la finalización del IRP se produce precisamente antes de que la solicitud de E/S se desenrede de nuevo en el controlador comprobado en la ruta de acceso de finalización. Esto significa que el STATUS_PENDING ruta de acceso del código del controlador comprobado se realiza realmente y el controlador comprobado percibe un retraso en la finalización.

Activación de esta opción

Para activar Forzar solicitudes de E/S pendientes, también debe activar la verificación de E/S. Puede activar la opción Forzar solicitudes de E/S pendientes para uno o varios controladores mediante el Administrador de comprobadores de controladores o la línea de comandos Verifier.exe. Para obtener más información, vea Seleccionar opciones del comprobador de controladores.

La opción Forzar solicitudes de E/S pendientes solo se admite en Windows Vista y versiones posteriores de Windows.

  • En la línea de comandos

    Para activar Forzar solicitudes de E/S pendientes, use un valor de marca de 0x210 o agregue 0x210 al valor de marca. Este valor activa la verificación de E/S (0x10) y forzar solicitudes de E/S pendientes (0x200).

    Por ejemplo:

    verifier /flags 0x210 /driver MyDriver.sys
    

    La opción estará activa después del siguiente arranque.

    Si intenta activar solo forzar solicitudes de E/S pendientes (comprobador /flags 0x200), el comprobador de controladores habilita automáticamente las solicitudes de E/S pendientes (0x200) y la comprobación de E/S.

    También puede activar y desactivar forzar solicitudes de E/S pendientes sin reiniciar el equipo agregando el parámetro /volatile al comando. Por ejemplo:

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

    Esta configuración es efectiva inmediatamente, pero se pierde al apagar o reiniciar el equipo. Para obtener más información, consulte Uso de la configuración volátil.

  • Uso del Administrador de comprobadores de controladores

    1. Inicie el Administrador de comprobadores de controladores. Escriba Comprobador en una ventana del símbolo del sistema.
    2. Seleccione Crear configuración personalizada (para desarrolladores de código) y, a continuación, haga clic en Siguiente.
    3. Seleccione Seleccionar configuración individual en una lista completa.
    4. Seleccione Verificación de E/S y Forzar solicitudes de E/S pendientes.

    Si selecciona solo Forzar solicitudes de E/S pendientes, el Administrador de comprobadores de controladores le recuerda que se requiere la verificación de E / S y ofrece habilitarla para usted.

Visualización de los resultados

Para ver los resultados de la prueba Forzar solicitudes de E/S pendientes, use la extensión del depurador !verifier con un valor de marca de 0x40.

Para obtener información sobre !comprobador, vea el tema !comprobador en la documentación herramientas de depuración para Windows .

Si la máquina de prueba se bloquea como resultado de la prueba Forzar solicitudes de E/S pendientes, puede usar el comando !comprobador 40 para encontrar la causa. En un seguimiento de pila actual, busque la dirección del IRP que usó recientemente el controlador. Por ejemplo, si usa el comando kP , que muestra el marco de pila de un subproceso, puede encontrar la dirección IRP entre los parámetros de función del seguimiento de pila actual. A continuación, ejecute !comprobador 40 y busque la dirección del IRP. Los seguimientos de pila de fuerza pendientes más recientes aparecen en la parte superior de la pantalla.

Por ejemplo, el siguiente seguimiento de pila de Pci.sys muestra su respuesta a Forzar solicitudes de E/S pendientes. La prueba no muestra ningún error en la 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

El seguimiento de la pila muestra que Acpi.sys estaba intentando completar IRP 8f84ef00. El comprobador de controladores ha forzado una finalización diferida, por lo que Acpi.sys devolvió STATUS_PENDING a pci! PciCallDownIrpStack. Si esta llamada hubiera provocado un bloqueo, el propietario del controlador tendría que revisar el código fuente de pci. PciCallDownIrpStack y revíselo para controlar el STATUS_PENDING correctamente.