Uso de E/S directa con PIO

Un controlador que usa E/S programado (PIO) en lugar de DMA debe asignar doblemente búferes de espacio de usuario en un intervalo de direcciones de espacio del sistema. 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 de PIO que usa E/S directa.

diagrama que ilustra la E/S directa para los dispositivos que usan pio.

En la ilustración se muestra cómo un dispositivo que usa PIO controla la misma tarea.

  1. Algunos intervalos de direcciones virtuales de espacio de usuario representan el búfer del subproceso actual, y ese contenido del búfer podría almacenarse realmente en algún número de páginas físicamente desconcertantes. Si la longitud del búfer es distinta de cero, el administrador de E/S crea una MDL para describir este búfer.

  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 o FSD comprueba la accesibilidad del búfer proporcionado por el usuario. Si el administrador de E/S ha creado una MDL, llama a MmProbeAndLockPages con una MDL, que especifica el intervalo de direcciones virtuales para el búfer de usuario. MmProbeAndLockPages también rellena el intervalo de direcciones físicos correspondiente en MDL.

  4. El administrador de E/S proporciona un puntero a MDL (MdlAddress) en un IRP que solicita una operación de transferencia. Hasta que el administrador de E/S o el sistema de archivos llame a MmUnlockPages después de que el controlador complete el IRP, las páginas físicas descritas en MDL permanecen bloqueadas y asignadas al búfer. Sin embargo, las direcciones virtuales de este tipo de MDL pueden ser invisibles (y no válidas), incluso antes de que el IRP se envíe al controlador del dispositivo o a cualquier controlador intermedio que pueda estar superpuesta por encima del controlador de dispositivo.

  5. Si el controlador requiere direcciones del sistema (virtual), el controlador llama a MmGetSystemAddressForMdlSafe con el puntero MdlAddress de IRP para asignar doblemente las direcciones virtuales de espacio de usuario de MDL a un intervalo de direcciones de espacio del sistema. En la ilustración anterior, AliasBuff representa el MDL que describe las direcciones asignadas doblemente.

  6. El controlador usa el intervalo de direcciones virtuales de espacio del sistema del MDL (AliasBuff) doblemente asignado para leer los datos en la memoria.

Cuando el controlador completa el IRP llamando a IoCompleteRequest, el administrador de E/S o el sistema de archivos libera el intervalo de espacio del sistema doblemente asignado de MDL si el controlador llamado MmGetSystemAddressForMdlSafe. El administrador de E/S o el sistema de archivos desbloquea las páginas descritas en MDL y elimina el MDL e IRP en nombre del controlador. Para mejorar el rendimiento, los controladores deben evitar asignar doblemente direcciones físicas MDL al espacio del sistema, como se describe en el paso 3, a menos que deban usar direcciones virtuales. Al hacerlo, se usan las entradas de la tabla de páginas del sistema innecesariamente y pueden disminuir el rendimiento del controlador y la escalabilidad. Además, el sistema podría bloquearse si se queda sin entradas de tabla de páginas, ya que la mayoría de los controladores más antiguos no pueden controlar esta situación.

Se garantiza que los búferes del subproceso de usuario actual y el propio subproceso residen en memoria física solo mientras ese subproceso está activo. Para el subproceso que se muestra en la ilustración anterior, el contenido del búfer de usuario podría paginarse en el almacenamiento secundario mientras se ejecutan los subprocesos de otro proceso. Cuando se ejecuta el subproceso de otro proceso, la memoria física del sistema para el búfer del subproceso solicitante se puede sobrescribir a menos que el administrador de memoria haya bloqueado y conservado las páginas físicas correspondientes que contienen el búfer del subproceso original.

Sin embargo, las direcciones virtuales del subproceso original para su búfer no permanecen visibles mientras otro subproceso está activo, incluso si el administrador de memoria conserva las páginas físicas del búfer. Por lo tanto, los controladores no pueden usar una dirección virtual devuelta por MmGetMdlVirtualAddress para acceder a la memoria. Los autores de llamadas de esta rutina deben pasar sus resultados a MapTransfer (junto con el puntero MdlAddress de IRP) para transferir datos mediante el sistema basado en paquetes o DMA de bus-master.