Compartir a través de


Acceso a búferes de datos en controladores UMDF 1.x

Advertencia

UMDF 2 es la versión más reciente de UMDF y sustituye a UMDF 1. Todos los controladores UMDF nuevos deben escribirse con UMDF 2. No se agregan nuevas características a UMDF 1 y hay compatibilidad limitada con UMDF 1 en versiones más recientes de Windows 10. Los controladores universales de Windows deben usar UMDF 2.

Para obtener más información, consulta Introducción con UMDF.

Para obtener información sobre el acceso a los búferes de datos para UMDF 2, consulte Acceso a búferes de datos en controladores WDF.

Cuando un controlador recibe una solicitud de control de E/S de lectura, escritura o dispositivo, el objeto de solicitud contiene un búfer de entrada o un búfer de salida, o ambos. (Algunas solicitudes de control de E/S de dispositivo proporcionan dos entradas, dos salidas o dos búferes de entrada/salida).

Los búferes de entrada contienen información que necesita el controlador. En el caso de las solicitudes de escritura, normalmente esta información es datos que un controlador de función debe enviar a un dispositivo. En el caso de las solicitudes de control de E/S del dispositivo, un búfer de entrada puede contener información que indica el tipo de operación que debe realizar el controlador.

Los búferes de salida reciben información del controlador. En el caso de las solicitudes de lectura, normalmente esta información es datos que recibe un controlador de función de un dispositivo. En el caso de las solicitudes de control de E/S del dispositivo, un búfer de salida puede recibir el estado u otra información que el código de control de E/S de la solicitud especificada.

La técnica que usa el controlador para acceder a los búferes de datos de una solicitud puede depender del método del controlador para acceder a los búferes de datos de un dispositivo. UMDF admite los siguientes métodos de acceso al búfer:

Un tercer método de acceso, que no se denomina ni E/S directa ni almacenado en búfer, no está disponible para los controladores basados en UMDF, pero UMDF puede convertir algunas solicitudes de E/S del método "ni" a un método que admita la versión de UMDF.

En la mayoría de los casos, los controladores basados en UMDF llaman a los mismos métodos de objeto UMDF para acceder a los búferes de datos, tanto si UMDF como el controlador usan E/S almacenada en búfer o E/S directa. La E/S directa suele proporcionar un mejor rendimiento que la E/S del búfer.

En las secciones siguientes de este tema se explica:

Especificar un método de acceso de búfer preferido

Las versiones 1.9 y posteriores de UMDF admiten los métodos de acceso de E/S almacenados en búfer y directo. Los controladores pueden especificar el método de acceso que prefiera usar para todas las solicitudes de control de E/S de lectura, escritura y dispositivo de un dispositivo llamando a IWDFDeviceInitialize2::SetIoTypePreference antes de llamar a IWDFDriver::CreateDevice para crear un objeto de dispositivo. Por ejemplo, si un controlador especifica una preferencia solo para el método de E/S almacenado en búfer para las solicitudes de lectura y escritura para uno de sus dispositivos, el proceso host del controlador UMDF usa el método de E/S almacenado en búfer cuando entrega solicitudes de lectura y escritura al controlador para ese dispositivo. Si un controlador especifica una preferencia para la E/S directa, UMDF puede (pero no) usar E/S directa. Para obtener más información sobre cuándo UMDF usa E/S directa, vea Cómo UMDF elige un método de acceso de búfer para una solicitud de E/S.

Para cada dispositivo que admita un controlador, el controlador puede especificar una preferencia para la E/S almacenada en búfer, para E/S directa o para E/S directa o almacenada en búfer para el dispositivo. El controlador puede especificar un tipo de método de acceso para las solicitudes de lectura y escritura y otro tipo de método de acceso para las solicitudes de control de E/S del dispositivo. Si el controlador no especifica una preferencia de método de acceso, UMDF usa el método almacenado en búfer.

En el caso de las solicitudes de control de E/S del dispositivo, el código de control de E/S (IOCTL) especifica el método de acceso al búfer. (Para obtener más información sobre cómo los IOCTLs especifican un método de acceso, consulte Definición de códigos de control de E/S). Sin embargo, el método de acceso que usa UMDF podría no coincidir con el método de acceso que especifica el IOCTL.

  • En las versiones de UMDF anteriores a la versión 1.9, UMDF siempre usa el método de acceso almacenado en búfer para todas las solicitudes de control de E/S.

  • Las versiones 1.9 y posteriores de UMDF usan el método de acceso de E/S almacenado en búfer si el IOCTL especifica la E/S almacenada en búfer. Si el IOCTL especifica E/S directa y si el controlador llama a IWDFDeviceInitialize2::SetIoTypePreference para indicar que una preferencia para la E/S directa, UMDF podría usar E/S directa o podría usar E/S almacenada en búfer, como se describe en How UMDF Chooses a Buffer Access Method for an I/O Request. Para obtener información sobre cómo UMDF admite ICTLs que especifican el método de E/S no almacenado en búfer ni E/S directa, consulte Using Nor Buffered I/O and Direct I/O in UMDF Drivers.

Especificar un modo de recuperación de búfer

En las versiones de UMDF anteriores a la versión 1.9, UMDF siempre hace que los búferes de una solicitud de E/S estén disponibles para el controlador (copiando los búferes en el proceso de host del controlador UMDF) en cuanto UMDF recibe la solicitud de E/S. Este modo de recuperación de búfer se denomina recuperación inmediata. Si se produce un error, UMDF completa la solicitud de E/S con un valor de estado de error y no entrega la solicitud de E/S al controlador.

Las versiones 1.9 y posteriores de UMDF admiten los modos de recuperación inmediata y recuperación diferida . El modo de recuperación diferido pospone copiar el búfer de una solicitud de E/S en el proceso host del controlador hasta que el controlador intenta acceder al búfer. Si se produce un error, las funciones de acceso al búfer devuelven un valor de estado de error al controlador.

El controlador puede especificar un modo de recuperación de búfer cuando llama a IWDFDeviceInitialize2::SetIoTypePreference para cada dispositivo. Use las reglas siguientes:

  • Si el controlador especifica el método de acceso de E/S directo, también debe especificar el modo de recuperación diferido. La E/S directa solo funciona con la recuperación diferida.

  • Todos los controladores que se escriben para ejecutarse con las versiones 1.9 y posteriores de UMDF deben especificar el modo de recuperación diferido para todas las solicitudes de E/S, tanto si el controlador elige el método de acceso de E/S almacenado en búfer o directo. La recuperación diferida proporciona un mejor rendimiento porque no tiene acceso a los búferes que el controlador no usa.

Si el controlador no especifica un modo de recuperación de búfer, UMDF usa la recuperación inmediata.

Todos los controladores basados en UMDF de una pila de controladores deben usar el mismo modo de recuperación. Si algunos controladores especifican la recuperación inmediata y algunas especifican la recuperación diferida, UMDF usa la recuperación inmediata.

Cómo UMDF elige un método de acceso de búfer para una solicitud de E/S

El método de acceso que especifica un controlador cuando llama a IWDFDeviceInitialize2::SetIoTypePreference, podría no ser el que usa UMDF. UMDF usa las siguientes reglas para determinar qué método de acceso se va a usar:

  • Todos los controladores basados en UMDF de una pila de controladores deben usar el mismo método para acceder a los búferes de un dispositivo. Si UMDF determina que algunos controladores prefieren E/S almacenados en búfer o E/S directa para un dispositivo, mientras que otros controladores prefieren solo E/S almacenados en búfer para el dispositivo, UMDF usa E/S almacenada en búfer para todos los controladores. Si uno o varios de los controladores de una pila prefieren solo E/S almacenados en búfer, mientras que otros prefieren solo E/S directa, UMDF registra un evento en el registro de eventos del sistema y no inicia la pila de controladores.

    El controlador puede llamar a IWDFDevice2::GetDeviceStackIoTypePreference para determinar los métodos de acceso de búfer que UMDF ha asignado a las solicitudes de control de lectura y escritura de un dispositivo y solicitudes de control de E/S.

  • En algunos casos, un controlador especifica una preferencia para la E/S directa cuando llama a IWDFDeviceInitialize2::SetIoTypePreference, pero para obtener el mejor rendimiento, UMDF usa la E/S almacenada en búfer para una o varias de las solicitudes del dispositivo. Por ejemplo, UMDF usa E/S almacenada en búfer para búferes pequeños si puede copiar los datos en el búfer del controlador más rápido de lo que puede asignar los búferes para el acceso directo.

    Opcionalmente, puede establecer un valor del Registro DirectTransferThreshold con tipo REG_DWORD que usa el marco para determinar el tamaño de búfer más pequeño para el que el marco usará E/S directa. Normalmente, no es necesario proporcionar este valor del Registro porque el marco usa un valor que proporciona el mejor rendimiento. El valor DirectTransferThreshold se encuentra bajo la subclave Device Parameters\WUDF del dispositivo, que se encuentra bajo la clave de hardware del dispositivo.

    El marco de trabajo usa las siguientes reglas para determinar el umbral en función del valor que proporcione en DirectTransferThreshold. Los números proporcionados suponen un PAGE_SIZE de 4096, que es válido excepto en sistemas basados en Itanium.

    • Si establece DirectTransferThreshold en cualquier valor menor o igual que 8192 (o 2 * PAGE_SIZE), el marco establece el umbral en 8192. El marco usa E/S almacenado en búfer para búferes menores de 8192 bytes y E/S directa para búferes igual o mayor que 8192 bytes.

    • Si establece DirectTransferThreshold en cualquier valor mayor que 8192, el marco redondea hasta el siguiente múltiplo exacto de PAGE_SIZE. De nuevo, el marco usa la E/S almacenada en búfer para los búferes más pequeños que el umbral y la E/S directa para los búferes igual o mayor que el umbral.

  • UMDF usa E/S directa solo para el espacio en búfer que comienza y termina en un límite de página de memoria. Si el principio o el final de un búfer no se encuentran en un límite de página, UMDF usa la E/S almacenada en búfer para esa parte del búfer. En otras palabras, UMDF puede usar E/S almacenada en búfer y E/S directa para una transferencia de datos grande que consta de varias solicitudes de E/S.

  • En el caso de las solicitudes de control de E/S de dispositivo, UMDF usa E/S directa solo si el código de control de E/S (IOCTL) especifica E/S directa y solo si todos los controladores basados en UMDF del dispositivo han llamado IWDFDeviceInitialize2::SetIoTypePreference para especificar el método de acceso directo.

Los controladores usan el mismo conjunto de métodos de objeto de solicitud para acceder a los búferes de datos, independientemente del método de acceso al búfer. Por lo tanto, la mayoría de los controladores normalmente no necesitan saber si UMDF usa E/S almacenada en búfer o E/S directa para una solicitud de E/S.

Cómo un controlador puede obtener el método de acceso para una solicitud de E/S

En algunos casos, puede mejorar el rendimiento del dispositivo y del controlador si se conoce el método de acceso. En tales casos, el controlador puede llamar a IWDFIoRequest2::GetEffectiveIoType para obtener un método de acceso al búfer de una solicitud de E/S.

Por ejemplo, considere un dispositivo de alto rendimiento que normalmente usa E/S directa. Dado que usa E/S directa, el controlador debe copiar parámetros especificados por la aplicación en la memoria del controlador local antes de validar los parámetros, para asegurarse de que la aplicación no modifica los parámetros después de la validación.

Dado que el controlador puede recibir ocasionalmente un búfer que usa E/S almacenado en búfer y, dado que los búferes de E/S almacenados en búfer ya se han copiado, la aplicación no puede modificar los datos y el controlador no tiene que copiar parámetros antes de validarlos. Por lo tanto, el controlador debe comprobar el método de acceso al búfer de cada solicitud para determinar si debe copiar parámetros antes de validarlos.

Uso de E/S almacenados en búfer en controladores UMDF

Si el controlador usa E/S almacenada en búfer, el comportamiento de UMDF varía en función del tipo de solicitud. Para las solicitudes de lectura y escritura, el proceso de host del controlador crea un único búfer intermedio al que puede acceder el controlador.

En el caso de las solicitudes de escritura, el proceso host del controlador transfiere la información de entrada del búfer de entrada de la aplicación que realiza la llamada antes de llamar a la pila de controladores. Los controladores suelen leer información de entrada del búfer intermedio y escribirla en el dispositivo.

Para las solicitudes de lectura, los controladores suelen leer información de un dispositivo y almacenarla en el búfer intermedio. El proceso de host del controlador copia los datos de salida del búfer intermedio en el búfer de salida de la aplicación.

Sin embargo, en el caso de las solicitudes de control de E/S del dispositivo, el proceso host del controlador crea dos búferes independientes a los que puede acceder el controlador. Tenga en cuenta que esto difiere del comportamiento de los controladores WDM y KMDF, para los que las solicitudes de control de E/S de lectura, escritura y E/S del dispositivo enviadas mediante E/S almacenadas en búfer almacenados en búfer tienen como resultado el acceso al controlador de un solo búfer intermedio. En este caso, el búfer de salida inicialmente no contiene nada y el controlador no debe leerlo. Además, los datos que el controlador escribe en el búfer de entrada se descartan y no se devuelven a la aplicación que realiza la llamada.

Para obtener instrucciones sobre cuándo elegir E/S almacenada en búfer, consulte WDF_DEVICE_IO_TYPE.

Las versiones 1.9 y posteriores de UMDF pueden admitir la recuperación inmediata o diferida de búferes de solicitudes. Para obtener más información, consulte WDF_DEVICE_IO_BUFFER_RETRIEVAL.

Un controlador que use el modo de recuperación de búfer inmediato debe usar IWDFIoRequest::GetInputMemory e IWDFIoRequest::GetOutputMemory para acceder a los búferes.

Un controlador que usa el modo de recuperación de búfer diferido puede acceder a los búferes llamando a IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer o IWDFIoRequest2::RetrieveOutputMemory.

Uso de E/S directa en controladores UMDF

Si el controlador usa E/S directa, el proceso de host del controlador comprueba la accesibilidad del espacio de búfer que el originador de la solicitud de E/S (normalmente una aplicación en modo de usuario) especificada, bloquea el espacio en búfer en memoria física y, a continuación, proporciona al controlador acceso directo al espacio de búfer.

Para obtener instrucciones sobre cuándo elegir E/S directa, consulte WDF_DEVICE_IO_TYPE.

El controlador puede acceder a los búferes llamando a IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer o IWDFIoRequest2::RetrieveOutputMemory.

Usar ni E/S almacenado en búfer ni E/S directa en controladores UMDF

El método de acceso al búfer que se conoce como método de E /S no almacenado en búfer ni E/S directa (o bien, el método "ni", para abreviar) permite a los controladores acceder directamente a los punteros de búfer de solicitud de una aplicación. Los controladores basados en UMDF no pueden usar este método de acceso.

Sin embargo, las definiciones de algunos códigos de control de E/S de dispositivo (IOCTLs) especifican que las solicitudes usan el método "ninguno". Opcionalmente, UMDF puede convertir el método de acceso al búfer de estas solicitudes de control de E/S de dispositivo a E/S almacenadas en búfer o E/S directa. Siga estos pasos:

  1. Incluya la directiva UmdfMethodNeitherAction en una sección INF DDInstall del archivo INF del controlador. Puede establecer el valor de la directiva para indicar que UMDF debe pasar solicitudes de control de E/S del dispositivo que usan el método de acceso "ninguno" al controlador. (De lo contrario, UMDF completa estas solicitudes de E/S con un valor de estado de error).

  2. Acceda a los búferes de la solicitud de E/S mediante los métodos de objeto que UMDF proporciona para E /S almacenada en búfer o E/S directa.

Debe habilitar la compatibilidad con las solicitudes IOCTL que usan el método "ninguno" solo si está seguro de que UMDF puede convertir el método de acceso a E/S almacenado en búfer o E/S directa. Por ejemplo, si el IOCTL especifica una solicitud personalizada que no sigue las reglas de especificación del búfer que se describen en Descripciones de búfer para códigos de control de E/S, UMDF no puede convertir los búferes.