Partager via


Utilisation des E/S mises en mémoire tampon

Un pilote qui prend en charge un appareil interactif ou lent, ou qui transfère généralement des quantités de données relativement petites à la fois, doit utiliser la méthode de transfert d’E/S en mémoire tampon . L’utilisation d’E/S mises en mémoire tampon pour les petits transferts interactifs améliore l’utilisation globale de la mémoire physique, car le gestionnaire de mémoire n’a pas besoin de verrouiller une page physique complète pour chaque transfert, comme il le fait pour les pilotes qui demandent des E/S directes. En règle générale, les pilotes vidéo, clavier, souris, série et parallèle demandent des E/S mises en mémoire tampon.

Le gestionnaire d’E/S détermine qu’une opération d’E/S utilise des E/S mises en mémoire tampon comme suit :

La figure suivante illustre la façon dont le gestionnaire d’E/S configure une demande de IRP_MJ_READ pour une opération de transfert qui utilise des E/S mises en mémoire tampon.

diagramme illustrant une e/s mise en mémoire tampon pour les mémoires tampons utilisateur.

La figure montre une vue d’ensemble de la façon dont les pilotes peuvent utiliser le pointeur SystemBuffer dans l’IRP pour transférer des données pour une demande de lecture, lorsqu’un pilote a ORed les indicateurs de l’objet de périphérique avec DO_BUFFERED_IO :

  1. Une certaine 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 être stocké quelque part dans une plage d’adresses physiques basées sur la page (trame sombre dans la figure précédente).

  2. 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.

  3. Le gestionnaire d’E/S vérifie l’accessibilité de la mémoire tampon fournie par l’utilisateur et appelle ExAllocatePoolWithTag pour créer une mémoire tampon d’espace système non paginé (SystemBuffer) de la taille de la mémoire tampon fournie par l’utilisateur.

  4. Le gestionnaire d’E/S fournit l’accès au SystemBuffer nouvellement alloué dans l’IRP qu’il envoie au pilote.

    Si la figure affichait une demande d’écriture, le gestionnaire d’E/S copierait les données de la mémoire tampon utilisateur dans la mémoire tampon système avant d’envoyer l’IRP au pilote.

  5. Pour la demande de lecture illustrée dans la figure précédente, le pilote lit les données de l’appareil dans la mémoire tampon de l’espace système. La mémoire de cette mémoire tampon est sans page et le pilote peut accéder en toute sécurité à la mémoire tampon sans la verrouiller au préalable. Une fois la demande de lecture satisfaite, le pilote appelle IoCompleteRequest avec l’IRP.

  6. Lorsque le thread d’origine est à nouveau actif, le gestionnaire d’E/S copie les données de lecture de la mémoire tampon système dans la mémoire tampon utilisateur. Il appelle également ExFreePool pour libérer la mémoire tampon système.

Une fois que le gestionnaire d’E/S a créé une mémoire tampon d’espace système pour le pilote, le thread en mode utilisateur demandeur peut être échangé et sa mémoire physique peut être réutilisée par un autre thread, éventuellement par un thread appartenant à un autre processus. Toutefois, la plage d’adresses virtuelles de l’espace système fournie dans l’IRP reste valide jusqu’à ce que le pilote appelle IoCompleteRequest avec l’IRP.

Les pilotes qui transfèrent de grandes quantités de données à la fois, en particulier les pilotes qui effectuent des transferts multipage, ne doivent pas tenter d’utiliser les E/S mises en mémoire tampon. Au fur et à mesure que le système s’exécute, le pool non paginé peut devenir fragmenté de sorte que le gestionnaire d’E/S ne peut pas allouer de mémoires tampons d’espace système contiguës volumineuses pour envoyer des IRP pour un tel pilote.

En règle générale, un pilote utilise des E/S mises en mémoire tampon pour certains types d’irps, tels que les requêtes IRP_MJ_DEVICE_CONTROL , même s’il utilise également des E/S directes. Les pilotes qui utilisent des E/S directes le font généralement uniquement pour les demandes de IRP_MJ_READ et de IRP_MJ_WRITE , et éventuellement les demandes de IRP_MJ_INTERNAL_DEVICE_CONTROL définies par le pilote qui nécessitent des transferts de données volumineux.

Chaque demande IRP_MJ_DEVICE_CONTROL et IRP_MJ_INTERNAL_DEVICE_CONTROL comprend un code de contrôle d’E/S. Si le code de contrôle d’E/S indique que l’IRP doit être pris en charge à l’aide d’E/S mises en mémoire tampon, le gestionnaire d’E/S utilise une mémoire tampon système unique pour représenter les mémoires tampons d’entrée et de sortie de l’application utilisateur. Un pilote qui prend en charge un tel code de contrôle d’E/S doit lire les données d’entrée (le cas échéant) à partir de la mémoire tampon, puis fournir des données de sortie (le cas échéant) en remplaçant les données d’entrée. Pour plus d’informations, consultez Définition de codes de contrôle d’E/S.