Macro MmLockPagableCodeSection (wdm.h)
La routine MmLockPagableCodeSection verrouille une section de code de pilote, contenant un ensemble de routines de pilotes marquées avec une directive de compilateur spéciale, dans l’espace système.
Syntaxe
void MmLockPagableCodeSection(
[in] Address
);
Paramètres
[in] Address
Spécifie une adresse symbolique. Cette adresse est généralement le nom d’une fonction de pilote dans une section de code de pilote qui a été marquée avec quelque chose comme #pragma alloc_text (PAGExxxx, driverfunction). Toutes les fonctions de la section PAGExxxx sont alors garanties d’être verrouillées lorsque cette fonction est retournée.
Valeur de retour
None
Remarques
MmLockPagableCodeSection retourne une valeur opaque que le système d’exploitation utilise pour identifier cette section du code du pilote. Cette valeur opaque peut être passée par la suite à MmLockPagableSectionByHandle (si le pilote déverrouille puis rebloque la section) ou à MmUnlockPagableImageSection.
La routine MmLockPagableCodeSection et MmUnlockPagableImageSection (la routine qui effectue l’action inverse) prennent en charge les pilotes qui peuvent effectuer les opérations suivantes :
Différer le chargement d’un sous-ensemble de routines de pilote dans la mémoire résidente jusqu’à ce que les demandes d’E/S entrantes pour les périphériques du pilote rendent nécessaire pour ces routines de traiter les IRP.
Rendez le même sous-ensemble de routines de pilotes disponibles pour la pagination quand ils ont terminé le traitement des demandes d’E/S et qu’aucune demande supplémentaire pour les périphériques du pilote n’est actuellement attendue.
MmLockPagableCodeSection, MmLockPagableSectionByHandle et MmUnlockPagableImageSection sont destinés à être utilisés par les pilotes de périphérique et intermédiaires qui ont les caractéristiques suivantes :
Le pilote a des chemins de code qui peuvent ne pas être nécessaires pendant l’exécution du système, mais, s’ils sont nécessaires, le code du pilote doit être résident, car il s’exécute dans un contexte de thread arbitraire ou à l’emplacement IRQL >= DISPATCH_LEVEL.
Le pilote peut déterminer exactement quand les routines paginables doivent être chargées et quand elles peuvent être à nouveau paginées.
Par exemple, le pilote de disque à tolérance de panne fourni par le système prend en charge la création de jeux de miroir, de jeux de bandes et de jeux de volumes. Pourtant, une machine particulière ne peut être configurée qu’avec un miroir défini, uniquement avec un jeu de bandes, uniquement avec un jeu de volumes ou avec une combinaison de ces trois options possibles. Dans ces circonstances, le pilote ftdisk système réduit la taille de son image chargée en marquant les routines qui prennent explicitement en charge les jeux de miroir, de bandes et de volumes comme appartenant à des sections de code paginables. Pendant l’initialisation du pilote, les sections de code paginables sont rendues résidentes uniquement si l’utilisateur a configuré les disques pour avoir des jeux de miroir, de bandes ou de volumes. Si l’utilisateur repartit les disques de manière dynamique, le pilote ftdisk verrouille toutes les sections de code paginable supplémentaires nécessaires pour prendre en charge les jeux de miroir, de bandes ou de volumes que l’utilisateur demande.
Dans d’autres exemples, les pilotes série et parallèles fournis par le système ont des routines DispatchCreate et DispatchClose qui sont appelées lorsqu’un port particulier est ouvert pour les E/S exclusives et lorsque le handle d’un port ouvert est libéré, respectivement. Pourtant, les demandes d’E/S en série et parallèles sont sporadiques, déterminées par les applications que l’utilisateur final exécute actuellement et les options d’application que l’utilisateur final exerce actuellement. Dans ces circonstances, les pilotes série et parallèles système réduisent la taille de leurs images chargées en marquant de nombreuses routines comme appartenant à une section de code paginable que la routine DispatchCreate rend résidente uniquement lorsque le premier port est ouvert pour les E/S.
Notez que chacun des pilotes système précédents remplit les deux critères pour avoir des sections paginables : le pilote a des chemins de code qui peuvent ne pas être nécessaires pendant l’exécution du système, et le pilote peut déterminer exactement quand sa section paginable doit être chargée et peut être paginée à nouveau.
Étant donné qu’il s’agit d’une opération coûteuse pour verrouiller une section, si un pilote verrouille une section de code paginable à plusieurs endroits, utilisez MmLockPagableCodeSection pour la première requête. Effectuez les demandes de verrouillage suivantes en appelant MmLockPagableSectionByHandle en passant le handle retourné par MmLockPagableCodeSection. Le verrouillage par handle améliore considérablement les performances du pilote, car le gestionnaire de mémoire utilise la valeur de retour opaque pour localiser rapidement la section appropriée au lieu de rechercher une liste de modules chargée. Une section verrouillée est déverrouillée en appelant MmUnlockPagableImageSection.
Chaque routine de pilote dans une section de code paginable doit être marquée avec la directive de compilateur suivante :
#pragma alloc_text(PAGExxxx, DriverRoutine)
où xxxx est un identificateur unique de quatre caractères facultatif pour la section paginable de l’appelant et DriverRoutine est un point d’entrée à inclure dans la section de code paginable. Les mot clé PAGE et le suffixe déterminé par le pilote, qui peuvent contenir jusqu’à quatre caractères, respectent la casse ; autrement dit, PAGE doit être en majuscules.
Un seul appel à MmLockPagableCodeSection dans, par exemple, la routine DispatchCreate d’un pilote entraîne le verrouillage de la section entière, qui contient chaque routine de pilote marquée avec le même identificateur PAGExxxx , dans l’espace système.
Certains types de routines de pilotes ne peuvent pas faire partie de la section paginable d’un pilote, y compris les éléments suivants :
Ne jamais rendre un ISR paginable. Il est possible qu’un pilote de périphérique reçoive une interruption fallacieuse même si son appareil n’est pas utilisé, en particulier si le vecteur d’interruption peut être partagé. En général, même si un pilote peut désactiver explicitement les interruptions sur son appareil, un ISR ne doit pas être rendu paginable.
Ne rendez jamais une routine DPC paginable si le pilote ne peut pas contrôler le moment où la DPC est mise en file d’attente, par exemple toute routine DpcForIsr ou CustomDpc qui peut être mise en file d’attente à partir d’un ISR. En général, les routines de pilote qui s’exécutent à IRQL >= DISPATCH_LEVEL et qui peuvent être appelées dans un contexte de thread arbitraire ou en réponse à un événement externe aléatoire ne doivent pas être paginables.
Ne jamais rendre la routine DispatchRead ou DispatchWrite paginable dans un pilote pouvant faire partie du chemin d’E/S de pagination du système. Le pilote d’un disque qui peut contenir le fichier de page système doit avoir des routines DispatchRead et DispatchWrite qui sont résidantes pendant l’exécution du système, de même que tous les pilotes superposés au-dessus d’un pilote de disque.
Notez que les routines dans une section paginable marquées avec la directive du compilateur #pragma alloc_text(PAGExxxx, ...) diffèrent des routines marquées avec la directive du compilateur #pragma alloc_text(INIT, ...). Les routines de la section INIT ne sont pas paginables et sont ignorées dès que le pilote revient de sa routine DriverEntry ou Reinitialize , le cas échéant.
Le gestionnaire de mémoire gère un nombre de verrous internes sur toute section paginable du pilote. Les appels à MmLockPagableCodeSection incrémentent ce nombre et le mmUnlockPagableImageSection réciproque décrémente le nombre. La section paginable d’un pilote n’est pas disponible pour être paginée, sauf si ce nombre est égal à zéro.
Pour plus d’informations sur la création de sections de code paginables, consultez Rendre les pilotes paginables.
Configuration requise
Condition requise | Valeur |
---|---|
Plateforme cible | Desktop (Expérience utilisateur) |
En-tête | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
Bibliothèque | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | <=APC_LEVEL |