Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Certains pilotes en mode noyau, tels que les pilotes série et parallèle, n’ont pas besoin d’être résidants en mémoire, sauf si les appareils qu’ils gèrent sont ouverts. Toutefois, tant qu’il existe une connexion ou un port actif, une partie du code de pilote qui gère ce port doit être résident pour traiter l’appareil. Lorsque le port ou la connexion n’est pas utilisé, le code du pilote n’est pas obligatoire. En revanche, un pilote pour un disque qui contient du code système, du code d’application ou du fichier de pagination système doit toujours être résident en mémoire, car le pilote transfère constamment les données entre son appareil et le système.
Un pilote pour un appareil utilisé de manière sporadique (par exemple, un modem) peut libérer de l’espace système lorsque l’appareil qu’il gère n’est pas actif. Si vous placez dans une seule section le code qui doit être résident pour traiter un appareil actif et si votre pilote verrouille le code en mémoire pendant que l’appareil est utilisé, vous pouvez désigner cette section comme pouvant être paginable. Lorsque l’appareil du pilote est ouvert, le système d’exploitation place la section paginable en mémoire et le pilote le verrouille jusqu’à ce qu’il n’y ait plus besoin.
Le code du pilote audio CD système utilise cette technique. Le code du pilote est regroupé en sections paginables selon le fabricant du périphérique CD. Certaines marques ne peuvent jamais être présentes sur un système donné. En outre, même si un CD-ROM existe sur un système, il est souvent accessible, de sorte que le regroupement de code en sections paginables par type CD garantit que le code des appareils qui n’existent pas sur un ordinateur particulier n’est jamais chargé. Toutefois, lorsque l’appareil est accessible, le système charge le code de l’appareil CD approprié. Then the driver calls the MmLockPagableCodeSection routine, as described later in this article, to lock its code into memory while its device is being used.
Pour isoler le code paginable dans une section nommée, marquez-le avec la directive du compilateur suivante :
#pragma alloc_text(PAGE*Xxx***, *RoutineName***)
The name of a pageable code section must start with the four letters "PAGE" and can be followed by up to four characters (represented here as Xxx) to uniquely identify the section. Les quatre premières lettres du nom de la section (autrement dit, « PAGE ») doivent être majuscules. The RoutineName identifies an entry point to be included in the pageable section.
Le nom valide le plus court pour une section de codes paginable dans un fichier de pilote est simplement PAGE. Par exemple, la directive pragma de l’exemple de code suivant identifie RdrCreateConnection comme point d’entrée dans une section de codes paginable nommée PAGE.
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RdrCreateConnection)
#endif
To make pageable driver code resident and locked in memory, a driver calls MmLockPagableCodeSection, passing an address (typically the entry point of a driver routine) that's in the pageable code section. MmLockPagableCodeSection locks in the whole contents of the section that contains the routine referenced in the call. In other words, this call makes every routine associated with the same PAGEXxx identifier resident and locked in memory.
MmLockPagableCodeSection returns a handle to be used when unlocking the section (by calling the MmUnlockPagableImageSection routine) or when the driver must lock the section from additional locations in its code.
Un pilote peut également traiter les données rarement utilisées comme paginables afin qu’elles puissent également être paginées jusqu’à ce que l’appareil pris en charge soit actif. Par exemple, le pilote de mélangeur système utilise des données paginables. L’appareil mixer n’a pas d’E/S asynchrones qui lui sont associées. Ce pilote peut donc rendre ses données paginables.
Le nom d’une section de données paginables doit commencer par les quatre lettres « PAGE » et peut être suivi de jusqu’à quatre caractères pour identifier de manière unique la section. Les quatre premières lettres du nom de la section (autrement dit, « PAGE ») doivent être majuscules.
Évitez d’attribuer des noms identiques aux sections de code et de données. Pour rendre le code source plus lisible, les développeurs de pilotes attribuent généralement le nom PAGE à la section de codes paginables, car ce nom est court et peut apparaître dans de nombreuses directives pragma alloc_text. Les noms plus longs sont ensuite attribués à toutes les sections de données paginables (par exemple, PAGEDATA pour data_seg, PAGEBSS pour bss_seg, et ainsi de suite) dont le pilote peut avoir besoin.
Par exemple, les deux premières directives pragma de l’exemple de code suivant définissent deux sections de données paginables, PAGEDATA et PAGEBSS. PAGEDATA est déclaré à l’aide de la directive pragma data_seg et contient des données initialisées. PAGEBSS est déclaré à l’aide de la directive bss_seg pragma et contient des données non initialisées.
#pragma data_seg("PAGEDATA")
#pragma bss_seg("PAGEBSS")
INT Variable1 = 1;
INT Variable2;
CHAR Array1[64*1024] = { 0 };
CHAR Array2[64*1024];
#pragma data_seg()
#pragma bss_seg()
Dans cet exemple de code, Variable1 et Array1 sont explicitement initialisés et sont donc placés dans la section PAGEDATA.
Variable2 et Array2 sont implicitement initialisés à zéro et sont placés dans la section PAGEBSS.
L’initialisation implicite de variables globales à zéro réduit la taille du fichier exécutable sur disque et est préférée à l’initialisation explicite à zéro. L’initialisation explicite de zéro doit être évitée, sauf dans les cas où elle est requise pour placer une variable dans une section de données spécifique.
To make a data section memory-resident and lock it in memory, a driver calls MmLockPagableDataSection, passing a data item that appears in the pageable data section. MmLockPagableDataSection returns a handle to be used in subsequent locking or unlocking requests.
To restore a locked section's pageable status, call MmUnlockPagableImageSection, passing the handle value returned by MmLockPagableCodeSection or MmLockPagableDataSection, as appropriate. A driver's Unload routine must call MmUnlockPagableImageSection to release each handle it obtains for lockable code and data sections.
Le verrouillage d’une section est une opération coûteuse, car le gestionnaire de mémoire doit rechercher dans sa liste de modules chargée avant de verrouiller les pages en mémoire. If a driver locks a section from many locations in its code, it should use the more efficient MmLockPagableSectionByHandle after its initial call to MmLockPagableXxxSection.
The handle passed to MmLockPagableSectionByHandle is the handle returned by the earlier call to MmLockPagableCodeSection or MmLockPagableDataSection.
The memory manager maintains a count for each section handle and increments this count every time that a driver calls MmLockPagableXxx for that section. A call to MmUnlockPagableImageSection decrements the count. Bien que le compteur de n’importe quel handle de section ne soit pas différent de zéro, cette section reste verrouillée en mémoire.
Le handle d’une section est valide tant que son pilote est chargé. Therefore, a driver should call MmLockPagableXxxSection only one time. If the driver requires more locking calls, it should use MmLockPagableSectionByHandle.
If a driver calls any MmLockPagableXxx routine for a section that's already locked, the memory manager increments the reference count for the section. Si la section est paginée lorsque la routine de verrouillage est appelée, les pages du gestionnaire de mémoire de la section et définissent son nombre de références sur un.
L’utilisation de cette technique réduit l’effet du pilote sur les ressources système. Lorsque le pilote s’exécute, il peut verrouiller en mémoire le code et les données qui doivent être résidentes. Lorsqu’il n’existe aucune demande d’E/S en attente pour son appareil (autrement dit, lorsque l’appareil est fermé ou si l’appareil n’a jamais été ouvert), le pilote peut déverrouiller le même code ou les mêmes données, le rendant disponible pour être paginé.
Toutefois, une fois qu’un pilote connecte des interruptions, tout code de pilote qui peut être appelé pendant le traitement des interruptions doit toujours être résident en mémoire. Bien que certains pilotes de périphérique puissent être mis en page ou verrouillés en mémoire à la demande, certains ensembles de cœurs de ce code et de données d’un pilote doivent être résidant définitivement dans l’espace système.
Tenez compte des instructions d’implémentation suivantes pour verrouiller un code ou une section de données.
The primary use of the Mm(Un)LockXxx routines is to enable normally nonpaged code or data to be made pageable and brought in as nonpaged code or data. Les pilotes tels que le pilote série et le pilote parallèle sont de bons exemples : s’il n’y a pas de handles ouverts sur un périphérique géré par ce type de pilote, les parties du code ne sont pas nécessaires et peuvent rester paginées. Le redirecteur et le serveur sont également de bons exemples de pilotes qui peuvent utiliser cette technique. Lorsqu’il n’existe aucune connexion active, ces deux composants peuvent être paginés.
Toute la section paginable est verrouillée en mémoire.
Une section pour le code et une pour les données par pilote est efficace. De nombreuses sections nommées et paginables sont généralement inefficaces.
Conservez des sections purement paginables et paginées, mais verrouillées à la demande, distinctes.
Remember that MmLockPagableCodeSection and MmLockPagableDataSection shouldn't be frequently called. Ces routines peuvent entraîner une activité d’E/S importante lorsque le gestionnaire de mémoire charge la section. If a driver must lock a section from several locations in its code, it should use MmLockPagableSectionByHandle.