Share via


Uso de E/S almacenada en búfer

Un controlador que atiende un dispositivo interactivo o lento, o uno que normalmente transfiere cantidades relativamente pequeñas de datos a la vez, debe usar el método de transferencia de E/S almacenado en búfer . El uso de E/S almacenada en búfer para transferencias pequeñas e interactivas mejora el uso general de la memoria física, ya que el administrador de memoria no necesita bloquear una página física completa para cada transferencia, ya que para los controladores que solicitan E/S directa. Por lo general, el vídeo, el teclado, el mouse, el serial y los controladores paralelos solicitan E/S almacenada en búfer.

El administrador de E/S determina que una operación de E/S usa E/S almacenada en búfer como se indica a continuación:

En la ilustración siguiente se muestra cómo el administrador de E/S configura una solicitud de IRP_MJ_READ para una operación de transferencia que usa E/S almacenada en búfer.

diagrama que ilustra una E/S almacenada en búfer para los búferes de usuario.

En la ilustración se muestra información general sobre cómo los controladores pueden usar el puntero SystemBuffer en el IRP para transferir datos de una solicitud de lectura, cuando un controlador tiene ORed en las marcas del objeto de dispositivo con DO_BUFFERED_IO:

  1. Algunos intervalos de direcciones virtuales de espacio de usuario representan el búfer del subproceso actual y el contenido del búfer podría almacenarse en algún lugar dentro de un intervalo de direcciones físicas basadas en páginas (sombreado oscuro en la ilustración anterior).

  2. El administrador de E/S atiende la solicitud de lectura del subproceso actual, para la que el subproceso pasa un intervalo de direcciones virtuales de espacio de usuario que representan un búfer.

  3. El administrador de E/S comprueba la accesibilidad del búfer proporcionado por el usuario y llama a ExAllocatePoolWithTag para crear un búfer de espacio del sistema (SystemBuffer) no paginado del tamaño del búfer proporcionado por el usuario.

  4. El administrador de E/S proporciona acceso al systemBuffer recién asignado en el IRP que envía al controlador.

    Si la figura muestra una solicitud de escritura, el administrador de E/S copiaría datos del búfer de usuario en el búfer del sistema antes de enviar el IRP al controlador.

  5. Para la solicitud de lectura que se muestra en la ilustración anterior, el controlador lee los datos del dispositivo en el búfer de espacio del sistema. La memoria de este búfer no está paginada y el controlador puede acceder de forma segura al búfer sin bloquearlo primero. Cuando se haya satisfecho la solicitud de lectura, el controlador llama a IoCompleteRequest con irP.

  6. Cuando el subproceso original vuelve a estar activo, el administrador de E/S copia los datos de lectura del búfer del sistema en el búfer de usuario. También llama a ExFreePool para liberar el búfer del sistema.

Una vez que el administrador de E/S ha creado un búfer de espacio del sistema para el controlador, el subproceso en modo de usuario solicitante se puede intercambiar y otro subproceso puede reutilizar su memoria física, posiblemente por un subproceso que pertenezca a otro proceso. Sin embargo, el intervalo de direcciones virtuales del espacio del sistema proporcionado en IRP sigue siendo válido hasta que el controlador llama a IoCompleteRequest con irP.

Los controladores que transfieren grandes cantidades de datos a la vez, en particular, los controladores que realizan transferencias de página múltiple no deben intentar usar E/S almacenada en búfer. A medida que se ejecuta el sistema, el grupo no paginado se puede fragmentar para que el administrador de E/S no pueda asignar búferes de espacio del sistema grandes y contiguos para enviarlos en IRP para dicho controlador.

Normalmente, un controlador usa E/S almacenada en búfer para algunos tipos de IRP, como IRP_MJ_DEVICE_CONTROL solicitudes, incluso si también usa E/S directa. Los controladores que usan E/S directa normalmente solo lo hacen para las solicitudes de IRP_MJ_READ y IRP_MJ_WRITE , y posiblemente las solicitudes de IRP_MJ_INTERNAL_DEVICE_CONTROL definidas por el controlador que requieren transferencias de datos grandes.

Cada solicitud de IRP_MJ_DEVICE_CONTROL y IRP_MJ_INTERNAL_DEVICE_CONTROL incluye un código de control de E/S. Si el código de control de E/S indica que el IRP debe admitirse mediante E/S almacenada en búfer, el administrador de E/S usa un único búfer del sistema para representar los búferes de entrada y salida de la aplicación de usuario. Un controlador que admita este tipo de código de control de E/S debe leer los datos de entrada (si los hubiera) del búfer y, a continuación, proporcionar datos de salida (si los hubiera) sobrescribiendo los datos de entrada. Para obtener más información, consulte Definición de códigos de control de E/S.