Utilisation de listes de lookaside

Les pilotes qui doivent allouer dynamiquement des mémoires tampons de taille fixe pour effectuer des opérations d’E/S à la demande peuvent utiliser les routines de prise en charge ExXxxLookasideListEx ou ExXxxLookasideList . Une fois qu’un tel pilote initialise sa liste de lookaside, le système d’exploitation contient un certain nombre de mémoires tampons allouées dynamiquement de la taille donnée dans la liste de lookaside du pilote, réservant ainsi un ensemble de mémoires tampons réutilisables de taille fixe pour le pilote. Le format et le contenu des mémoires tampons de taille fixe d’un pilote (également appelés entrées) dans sa liste de lookaside sont déterminés par le pilote.

Par exemple, les pilotes de classe de stockage qui doivent configurer des blocs de requête SCSI pour les pilotes de port/miniport SCSI sous-jacents utilisent des listes de lookaside. Un tel pilote de classe alloue des mémoires tampons pour les SRB en fonction des besoins à partir de sa liste de lookaside et libère chaque mémoire tampon SRB dans la liste de lookaside pour la liste de lookaside à réutiliser chaque fois qu’un SRB est retourné au pilote de classe dans un IRP terminé. Étant donné qu’un pilote de classe de stockage ne peut pas déterminer le nombre de SDR qu’il doit utiliser à tout moment, car la demande d’E/S sur le pilote augmente et diminue, une liste de lookaside est un moyen pratique et économique de gérer l’allocation et la désallocation des mémoires tampons pour les SSR de taille fixe dans un tel pilote.

Le système d’exploitation conserve l’état de toutes les listes paginées et non paginées actuellement utilisées, en suivant dynamiquement la demande d’allocations et de désallocations d’entrées dans toutes les listes, et le pool système disponible pour les nouvelles entrées. Lorsque la demande d’allocations est élevée, le système d’exploitation augmente le nombre d’entrées qu’il contient dans chaque liste de lookaside. Lorsque la demande baisse à nouveau, elle libère les entrées de lookaside excédentaires dans le pool système.

Les listes de lookaside sont thread-safe. Une liste de lookaside dispose d’une synchronisation intégrée pour permettre à plusieurs threads en cours d’exécution simultanée dans un pilote de partager une liste de lookaside. Ces threads peuvent allouer en toute sécurité des mémoires tampons à partir de la liste de recherche partagée et libérer ces mémoires tampons dans la liste sans exiger que le pilote synchronise explicitement ces opérations. Toutefois, pour éviter d’éventuelles fuites et altérations de données, un ensemble de threads qui partagent une liste de lookaside doit synchroniser de manière explicite l’initialisation et la suppression de la liste.

Interfaces de liste de lookaside

À compter de Windows Vista, la structure LOOKASIDE_LIST_EX décrit une liste de lookaside qui peut contenir des mémoires tampons paginées ou non paginées. Si un pilote fournit des routines Allocate et Free personnalisées pour cette liste de lookaside, ces routines reçoivent un contexte privé en tant que paramètre d’entrée. Un pilote peut utiliser ce contexte pour collecter des données privées pour la liste de recherche. Par exemple, le contexte peut être utilisé pour compter le nombre d’entrées de liste qui sont allouées dynamiquement et libérées par la liste. Pour obtenir un exemple de code qui montre comment utiliser un contexte de cette façon, consultez ExInitializeLookasideListEx.

Les routines fournies par le système suivantes prennent en charge les listes de lookaside décrites par une structure de LOOKASIDE_LIST_EX :

ExAllocateFromLookasideListEx

ExDeleteLookasideListEx

ExFlushLookasideListEx

ExFreeToLookasideListEx

ExInitializeLookasideListEx

À compter de Windows 2000, la structure PAGED_LOOKASIDE_LIST décrit une liste de lookaside qui contient des mémoires tampons paginées. Si un pilote fournit des routines Allocate et Free personnalisées pour cette liste de lookaside, ces routines ne reçoivent pas de contexte privé en tant que paramètre d’entrée. Pour cette raison, si votre pilote est destiné à s’exécuter uniquement sur Windows Vista et les versions ultérieures de Windows, envisagez d’utiliser la structure LOOKASIDE_LIST_EX au lieu de la structure PAGED_LOOKASIDE_LIST pour vos listes de lookaside. Les routines fournies par le système suivantes prennent en charge les listes de lookaside décrites par une structure PAGED_LOOKASIDE_LIST :

ExAllocateFromPagedLookasideList

ExDeletePagedLookasideList

ExFreeToPagedLookasideList

ExInitializePagedLookasideList

À compter de Windows 2000, la structure NPAGED_LOOKASIDE_LIST décrit une liste de lookaside qui contient des mémoires tampons non paginés. Si un pilote fournit des routines Allocate et Free personnalisées pour cette liste de lookaside, ces routines ne reçoivent pas de contexte privé en tant que paramètre d’entrée. Là encore, si votre pilote est destiné à s’exécuter uniquement sur Windows Vista et les versions ultérieures de Windows, envisagez d’utiliser la structure LOOKASIDE_LIST_EX au lieu de la structure NPAGED_LOOKASIDE_LIST pour vos listes de lookaside. Les routines fournies par le système suivantes prennent en charge les listes de lookaside décrites par une structure de NPAGED_LOOKASIDE_LIST :

ExAllocateFromNPagedLookasideList

ExDeleteNPagedLookasideList

ExFreeToNPagedLookasideList

ExInitializeNPagedLookasideList

Instructions d’implémentation

Pour implémenter une liste de lookaside qui utilise une structure LOOKASIDE_LIST_EX , suivez les instructions de conception suivantes :

  • Appelez ExInitializeLookasideListEx pour configurer une liste de choix. Dans cet appel, spécifiez si les entrées de la liste de recherche doivent être paginées ou non paginées. Utilisez des mémoires tampons non paginés si le pilote lui-même ou tout pilote sous-jacent auquel il transmet ses entrées de liste de choix peut accéder à ces entrées à l’adresse IRQL >= DISPATCH_LEVEL. Utilisez des mémoires tampons paginées uniquement si les accès aux entrées de liste de recherche du pilote se produisent toujours à l’adresse IRQL <= APC_LEVEL.

  • La structure LOOKASIDE_LIST_EX de la liste de recherche doit toujours résider dans la mémoire système non paginée, que les entrées de la liste soient paginées ou non.

  • Pour de meilleures performances, transmettez des pointeurs NULL pour les paramètres Allocate et Free à ExInitializeLookasideListEx , sauf si les routines d’allocation et de désallocation doivent faire plus que simplement allouer et libérer de la mémoire pour les entrées de liste de recherche. Par exemple, ces routines peuvent enregistrer des informations sur l’utilisation par le pilote des mémoires tampons allouées dynamiquement.

  • Une routine Allocate fournie par un pilote peut passer les paramètres d’entrée (PoolType, Tag et Size) qu’elle reçoit directement à la routine ExAllocatePoolWithTag ou ExAllocatePoolWithQuotaTag pour allouer une nouvelle mémoire tampon.

  • Pour chaque appel à ExAllocateFromLookasideListEx, effectuez l’appel réciproque à ExFreeToLookasideListEx dès que possible chaque fois qu’une entrée précédemment allouée n’est plus utilisée.

La fourniture de routines Allocate et Free qui ne font rien de plus que d’appeler ExAllocatePoolWithTag et ExFreePool, respectivement, gaspille des cycles de processeur. ExAllocateFromLookasideListEx effectue automatiquement les appels nécessaires à ExAllocatePoolWithTag et ExFreePool lorsqu’un pilote transmet les pointeurs NullAllocate et Free à ExInitializeLookasideListEx.

Toute routine Allocate fournie par le pilote ne doit pas allouer de mémoire pour qu’une entrée du pool paginé soit conservée dans une liste de lookaside non paginée ou vice versa. Il doit également allouer des entrées de taille fixe, car tout appel de pilote suivant à ExAllocateFromLookasideListEx retourne la première entrée actuellement conservée dans la liste de recherche, sauf si la liste est vide. Autrement dit, un appel à ExAllocateFromLookasideListEx provoque un appel à la routine Allocate fournie par le pilote uniquement si la liste de lookaside donnée est actuellement vide. Par conséquent, à chaque appel à ExAllocateFromLookasideListEx, l’entrée retournée aura exactement la taille dont le pilote a besoin uniquement si toutes les entrées de la liste de lookaside ont une taille fixe. Une routine Allocate fournie par le pilote ne doit pas non plus modifier la valeur de balise que le pilote a initialement passée à ExInitializeLookasideListEx, car les modifications apportées à la valeur pool-balise rendent le débogage et le suivi de l’utilisation de la mémoire du pilote plus difficiles.

Les appels à ExFreeToLookasideListEx stockent les entrées précédemment allouées dans la liste de recherche, sauf si la liste est déjà complète (autrement dit, la liste contient le nombre maximal d’entrées déterminé par le système). Pour de meilleures performances, un pilote doit effectuer un appel réciproque à ExFreeToLookasideListEx aussi rapidement que possible pour chaque appel qu’il effectue à ExAllocateFromLookasideListEx. Lorsqu’un pilote libère rapidement des entrées dans sa liste de lookaside, le prochain appel de ce pilote à ExAllocateFromLookasideListEx est beaucoup moins susceptible d’entraîner une pénalité de performances en allouant dynamiquement de la mémoire pour une nouvelle entrée.

Des instructions similaires s’appliquent à une liste de lookaside qui utilise une structure PAGED_LOOKASIDE_LIST ou NPAGED_LOOKASIDE_LIST .