Utilisation d’E/S directes avec PIO
Un pilote qui utilise des E/S programmées (PIO) plutôt que DMA doit doublement mapper les mémoires tampons d’espace utilisateur dans une plage d’adresses d’espace système. La figure suivante illustre comment le gestionnaire d’E/S configure une demande de IRP_MJ_READ pour une opération de transfert PIO qui utilise des E/S directes.
La figure montre comment un appareil qui utilise piO gère la même tâche.
Une plage d’adresses virtuelles d’espace utilisateur représente la mémoire tampon du thread actuel, et le contenu de cette mémoire tampon peut en fait être stocké sur un certain nombre de pages physiquement discontigueuses. Si la longueur de la mémoire tampon n’est pas nulle, le gestionnaire d’E/S crée une MDL pour décrire cette mémoire tampon.
Le gestionnaire d’E/S traite la demande de lecture du thread actuel, pour laquelle le thread transmet une plage d’adresses virtuelles d’espace utilisateur représentant une mémoire tampon.
Le gestionnaire d’E/S ou le FSD vérifie l’accessibilité de la mémoire tampon fournie par l’utilisateur. Si le gestionnaire d’E/S a créé une MDL, il appelle MmProbeAndLockPages avec une MDL, qui spécifie la plage d’adresses virtuelles pour la mémoire tampon utilisateur. MmProbeAndLockPages remplit également la plage d’adresses physiques correspondante dans le MDL.
Le gestionnaire d’E/S fournit un pointeur vers le MDL (MdlAddress) dans un IRP qui demande une opération de transfert. Jusqu’à ce que le gestionnaire d’E/S ou le système de fichiers appelle MmUnlockPages une fois que le pilote a terminé l’IRP, les pages physiques décrites dans le MDL restent verrouillées et affectées à la mémoire tampon. Toutefois, les adresses virtuelles d’une telle MDL peuvent devenir invisibles (et non valides), même avant l’envoi de l’IRP au pilote de périphérique ou à tout pilote intermédiaire qui peut être superposé au pilote de périphérique.
Si le pilote a besoin d’adresses système (virtuelles), le pilote appelle MmGetSystemAddressForMdlSafe avec le pointeur MdlAddress de l’IRP pour mapper doublement les adresses virtuelles de l’espace utilisateur dans la MDL à une plage d’adresses d’espace système. Dans la figure ci-dessus, AliasBuff représente le MDL qui décrit les adresses doublement mappées.
Le pilote utilise la plage d’adresses virtuelles d’espace système du MDL (AliasBuff) doublement mappé pour lire les données en mémoire.
Lorsque le pilote termine l’IRP en appelant IoCompleteRequest, le gestionnaire d’E/S ou le système de fichiers libère la plage d’espace système doublement mappée du MDL si le pilote a appelé MmGetSystemAddressForMdlSafe. Le gestionnaire d’E/S ou le système de fichiers déverrouille les pages décrites dans le MDL et supprime le MDL et l’IRP pour le compte du pilote. Pour de meilleures performances, les pilotes doivent éviter de mapper doublement les adresses physiques MDL à l’espace système, comme décrit à l’étape 3, sauf s’ils doivent utiliser des adresses virtuelles. Cela utilise inutilement les entrées de table de pages système et peut réduire à la fois les performances et l’extensibilité des pilotes. En outre, le système peut se bloquer s’il manque d’entrées de table de page, car la plupart des pilotes plus anciens ne peuvent pas gérer cette situation.
Les mémoires tampons du thread utilisateur actuel et le thread lui-même sont garantis pour être résidents dans la mémoire physique uniquement pendant que ce thread est actif. Pour le thread illustré dans la figure précédente, le contenu de sa mémoire tampon utilisateur peut être paginé vers le stockage secondaire pendant l’exécution des threads d’un autre processus. Lorsque le thread d’un autre processus est exécuté, la mémoire physique système de la mémoire tampon du thread demandeur peut être remplacée, sauf si le gestionnaire de mémoire a verrouillé et conservé les pages physiques correspondantes qui contiennent la mémoire tampon du thread d’origine.
Toutefois, les adresses virtuelles du thread d’origine pour sa mémoire tampon ne restent pas visibles tant qu’un autre thread est actif, même si le gestionnaire de mémoire conserve les pages physiques de la mémoire tampon. Par conséquent, les pilotes ne peuvent pas utiliser une adresse virtuelle retournée par MmGetMdlVirtualAddress pour accéder à la mémoire. Les appelants de cette routine doivent passer ses résultats à MapTransfer (avec le pointeur MdlAddress de l’IRP) afin de transférer des données à l’aide d’un système basé sur des paquets ou d’un bus master DMA.