Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Algunos controladores en modo kernel, como los controladores serie y paralelo, no necesitan estar residentes en memoria a menos que los dispositivos que administran estén abiertos. Sin embargo, siempre que haya una conexión o puerto activo, parte del código de controlador que administra ese puerto debe estar residente para atender el dispositivo. Cuando no se usa el puerto o la conexión, el código del controlador no es necesario. Por el contrario, un controlador para un disco que contiene código del sistema, código de aplicación o el archivo de paginación del sistema siempre debe estar residente en memoria porque el controlador transfiere constantemente datos entre su dispositivo y el sistema.
Un controlador para un dispositivo usado esporádicamente (como un módem) puede liberar espacio en el sistema cuando el dispositivo que administra no está activo. Si coloca en una sola sección el código que debe estar residente para atender un dispositivo activo y, si el controlador bloquea el código en la memoria mientras se usa el dispositivo, puede designar esta sección como paginable. Cuando se abre el dispositivo del controlador, el sistema operativo pone la sección paginable en la memoria y el controlador lo bloquea hasta que ya no sea necesario.
El código del controlador de audio cd del sistema usa esta técnica. El código del controlador se agrupa en secciones paginables según el fabricante del dispositivo cd. Es posible que algunas marcas nunca estén presentes en un sistema determinado. Además, incluso si existe un CD-ROM en un sistema, es posible que se tenga acceso a él con poca frecuencia, por lo que la agrupación de código en secciones paginables por tipo de CD garantiza que el código de los dispositivos que no existen en un equipo determinado nunca se carga. Sin embargo, cuando se accede al dispositivo, el sistema carga el código para el dispositivo de CD adecuado. 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.
Para aislar el código paginable en una sección con nombre, marque el código con la siguiente directiva del compilador:
#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. Las cuatro primeras letras del nombre de sección (es decir, "PAGE") deben escribirse en mayúsculas. The RoutineName identifies an entry point to be included in the pageable section.
El nombre válido más corto para una sección de código paginable en un archivo de controlador es simplemente PAGE. Por ejemplo, la directiva pragma del ejemplo de código siguiente identifica RdrCreateConnection como punto de entrada en una sección de código paginable denominada 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 controlador también puede tratar los datos que rara vez se usan como paginables para que también se pueda paginar hasta que el dispositivo que admita esté activo. Por ejemplo, el controlador mezclador del sistema usa datos paginables. El dispositivo mezclador no tiene ninguna E/S asincrónica asociada, por lo que este controlador puede hacer que sus datos sean paginables.
El nombre de una sección de datos paginable debe comenzar con las cuatro letras "PAGE" y puede ir seguida de hasta cuatro caracteres para identificar de forma única la sección. Las cuatro primeras letras del nombre de sección (es decir, "PAGE") deben escribirse en mayúsculas.
Evite asignar nombres idénticos a secciones de código y datos. Para que el código fuente sea más legible, los desarrolladores de controladores suelen asignar el nombre PAGE a la sección de códigos paginables porque este nombre es corto y puede aparecer en numerosas directivas pragma de alloc_text. A continuación, se asignan nombres más largos a las secciones de datos paginables (por ejemplo, PAGEDATA para data_seg, PAGEBSS para bss_seg, etc.) que el controlador podría requerir.
Por ejemplo, las dos primeras directivas pragma del ejemplo de código siguiente definen dos secciones de datos paginables, PAGEDATA y PAGEBSS. PAGEDATA se declara mediante la directiva pragma de data_seg y contiene datos inicializados. PAGEBSS se declara mediante la directiva pragma bss_seg y contiene datos sin inicializar.
#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()
En este ejemplo de código, y Array1 se inicializan explícitamente y, por tanto, Variable1 se colocan en la sección PAGEDATA.
Variable2 y Array2 se inicializan implícitamente sin cero y se colocan en la sección PAGEBSS.
Inicializar implícitamente variables globales en cero reduce el tamaño del archivo ejecutable en disco y se prefiere sobre la inicialización explícita a cero. Se debe evitar la inicialización explícita de cero, excepto en los casos en los que es necesario para colocar una variable en una sección de datos específica.
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.
Bloquear una sección es una operación costosa porque el administrador de memoria debe buscar en su lista de módulos cargado antes de bloquear las páginas en la memoria. 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. Aunque el contador de cualquier identificador de sección es distinto de cero, esa sección permanece bloqueada en la memoria.
El identificador de una sección es válido siempre que se cargue su controlador. 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 sección se pagina cuando se llama a la rutina de bloqueo, las páginas del administrador de memoria de la sección y establecen su recuento de referencias en uno.
El uso de esta técnica minimiza el efecto del controlador en los recursos del sistema. Cuando se ejecuta el controlador, puede bloquear en memoria el código y los datos que deben estar residentes. Cuando no hay solicitudes de E/S pendientes para su dispositivo (es decir, cuando el dispositivo está cerrado o si el dispositivo nunca se abrió), el controlador puede desbloquear el mismo código o datos, lo que hace que esté disponible para paginarse.
Sin embargo, después de que un controlador conecte interrupciones, cualquier código de controlador al que se pueda llamar durante el procesamiento de interrupciones siempre debe ser residente en memoria. Aunque algunos controladores de dispositivo se pueden hacer paginables o bloqueados en memoria a petición, algunos conjuntos principales de código y datos de este tipo de controlador deben residir permanentemente en el espacio del sistema.
Tenga en cuenta las siguientes directrices de implementación para bloquear un código o una sección de datos.
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. Los controladores como el controlador serie y el controlador paralelo son buenos ejemplos: si no hay identificadores abiertos para un dispositivo que administra un controlador, las partes del código no son necesarias y pueden permanecer paginadas. El redirector y el servidor también son buenos ejemplos de controladores que pueden usar esta técnica. Cuando no hay conexiones activas, ambos componentes se pueden paginar.
Toda la sección paginable está bloqueada en la memoria.
Una sección para el código y otra para los datos por controlador es eficaz. Muchas secciones con nombre que se pueden paginar suelen ser ineficaces.
Mantenga las secciones puramente paginables y las secciones paginadas pero bloqueadas a petición separadas.
Remember that MmLockPagableCodeSection and MmLockPagableDataSection shouldn't be frequently called. Estas rutinas pueden provocar una actividad de E/S intensa cuando el administrador de memoria carga la sección. If a driver must lock a section from several locations in its code, it should use MmLockPagableSectionByHandle.