Finalización de solicitudes de E/S

Cada controlador basado en marcos debe completar finalmente todas las solicitudes de E/S que recibe del marco. Los controladores completan las solicitudes llamando al método WdfRequestComplete, WdfRequestCompleteWithInformation o WdfRequestCompleteWithPriorityBoost del objeto de solicitud.

Cuándo completar una solicitud

Un controlador debe completar una solicitud cuando determina que se cumple uno de los siguientes casos:

  • La operación de E/S solicitada ha finalizado correctamente.

  • Se inició la operación de E/S solicitada, pero se produjo un error antes de finalizar.

  • No se admite la operación de E/S solicitada o no era válida en el momento en que se recibió y no se pudo iniciar.

  • Se canceló la operación de E/S solicitada.

Si el controlador atiende la solicitud de E/S mediante la creación de una actividad de E/S en el dispositivo, el controlador normalmente llama a WdfRequestComplete desde su función de devolución de llamada EvtInterruptDpc o EvtDpcFunc .

Si el controlador recibe una solicitud no admitida o no válida, normalmente llama a WdfRequestComplete desde el controlador de solicitudes que recibió la solicitud.

Si se canceló la operación de E/S, el controlador normalmente llama a WdfRequestComplete desde su función de devolución de llamada EvtRequestCancel .

Si el controlador reenvía la solicitud de E/S a un destino de E /S, el controlador completa la solicitud una vez que el destino de E/S completa la solicitud, como se indica a continuación:

  • Si el controlador reenvía la solicitud de E/S de forma sincrónica al destino de E/S, la llamada del controlador al destino de E/S solo se devuelve después de que un controlador de nivel inferior haya completado la solicitud (a menos que se produzca un error). Una vez devuelto el destino de E/S, el controlador debe llamar a WdfRequestComplete.

  • Si el controlador reenvía la solicitud de E/S de forma asincrónica, querrá que se le notifique cuando un controlador de nivel inferior complete la solicitud. Si el controlador registra una función de devolución de llamada CompletionRoutine , el marco llama a esta función de devolución de llamada después de que el destino de E/S complete la solicitud. La función de devolución de llamada CompletionRoutine suele llamar a WdfRequestComplete.

Para registrar una función de devolución de llamada CompletionRoutine , el controlador debe llamar a WdfRequestSetCompletionRoutine antes de reenviar la solicitud de E/S a un destino de E/S.

Si el controlador no necesita recibir una notificación cuando un destino de E/S completa una solicitud de E/S reenviada asincrónicamente, el controlador no tiene que registrar una función de devolución de llamada CompletionRoutine . En su lugar, el controlador puede establecer la marca WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET al llamar a WdfRequestSend. En este caso, el controlador no llama a WdfRequestComplete.

Un controlador no completa una solicitud de E/S que ha creado llamando a WdfRequestCreate o WdfRequestCreateFromIrp. En su lugar, el controlador debe llamar a WdfObjectDelete para eliminar el objeto de solicitud, normalmente después de que un destino de E/S haya completado la solicitud.

Por ejemplo, un controlador puede recibir una solicitud de lectura o escritura para una cantidad de datos mayor que los destinos de E/S del controlador pueden controlarse a la vez. El controlador debe dividir los datos en varias solicitudes más pequeñas y enviar estas solicitudes más pequeñas a uno o varios destinos de E/S. Entre las técnicas para controlar esta situación se incluyen las siguientes:

  • Llamar a WdfRequestCreate para crear un único objeto de solicitud adicional que represente una solicitud más pequeña.

    El controlador puede enviar esta solicitud de forma sincrónica a un destino de E/S. La función de devolución de llamada CompletionRoutine de la solicitud más pequeña puede llamar a WdfRequestReuse para que el controlador pueda reutilizar la solicitud y enviarlo de nuevo al destino de E/S. Una vez que el destino de E/S completa la última de las solicitudes más pequeñas, la función de devolución de llamada CompletionRoutine puede llamar a WdfObjectDelete para eliminar el objeto de solicitud creado por el controlador y el controlador puede llamar a WdfRequestComplete para completar la solicitud original.

  • Llamar a WdfRequestCreate para crear varios objetos de solicitud adicionales que representen las solicitudes más pequeñas.

    Los destinos de E/S del controlador pueden procesar estas múltiples solicitudes más pequeñas de forma asincrónica. El controlador puede registrar una función de devolución de llamada CompletionRoutine para cada una de las solicitudes más pequeñas. Cada vez que se llama a la función de devolución de llamada CompletionRoutine , puede llamar a WdfObjectDelete para eliminar un objeto de solicitud creado por el controlador. Una vez que el destino de E/S completa todas las solicitudes más pequeñas, el controlador puede llamar a WdfRequestComplete para completar la solicitud original.

Proporcionar información de finalización

Cuando un controlador completa una solicitud, puede proporcionar opcionalmente información adicional a la que pueden acceder otros controladores. Por ejemplo, un controlador podría proporcionar el número de bytes transferidos para una solicitud de lectura o escritura. Para proporcionar esta información, el controlador puede realizar una de las siguientes acciones:

Obtener información de finalización

Para obtener información sobre una solicitud de E/S que haya completado otro controlador, un controlador puede:

Si un controlador envía una solicitud de E/S de forma sincrónica, normalmente llama a WdfRequestGetStatus, WdfRequestGetCompletionParams y WdfRequestGetInformation después de que se devuelva la llamada sincrónica. Si un controlador envía una solicitud de E/S de forma asincrónica, normalmente llama a estos métodos desde una función de devolución de llamada CompletionRoutine .

Para obtener más información sobre cómo completar las solicitudes de E/S, vea Sincronizar el código de cancelación y finalización.