Функции работы с памятью
Из всего вышеизложенного нужно выделить основные моменты:
- 1. Все адресное пространство процесса (контекст памяти) делится на
две области
- системное адресное пространство (верхние 2 Гб)
и пользовательское адресное пространство (нижние 2 Гб):
- Системное адресное пространство всегда одинаково,
вне зависимости от текущего контекста памяти.
- Пользовательское адресное пространство разное для
каждого контекста памяти.
- 2. Код пользовательского режима и режима ядра пользуется для доступа
к памяти разными селекторами:
- Для одного контекста памяти селекторы адресуют
одну и ту же физическую память, но с разными режимами доступа.
- Селекторы не имеют ничего общего с контекстом памяти.
- По селекторам для ядра можно получить доступ (по
крайней мере, для чтения) ко всему адресному пространству в данном
контексте памяти, а по селекторам для ядра - только для пользовательской
области памяти.
- 3. Код в пользовательском адресном пространстве всегда вытесняемый,
если не предприняты меры по созданию новой записи в каталоге страниц,
указывающих на невытесняемую память.
- 4. Код, работающий на уровне IRQL большем или равном DISPATCH_LEVEL,
может использовать только невыгружаемую память (соответственно, сам
код должен находиться в невыгружаемой памяти).
- 5. В ОС существуют функции для выполнения любой работы с памятью:
- Выделение/освобождение памяти в выгружаемой/невыгружаемой,
кешируемой/некешируемой памяти.
- Преобразование адресов памяти (виртуальный в физический,
физический в виртуальный).
- Проверка доступности памяти. Рассмотрим эти функции
более подробно.
Выделение памяти
PVOID ExAllocatePool(
IN POOLJTYPE PoolType,
IN ULONG NumberOfBytes) ; PVOID ExAllocatePoolWithTag(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes, IN ULONG Tag); Где: POOLJTYPE принимает следующие
значения:
Тип памяти
(PoolType)
|
Описание
|
NonPagedPool
|
Обычное
выделение памяти из Nonpaged Pool.
|
NonPagedPoolCacheAligned
|
Выделение
памяти из Nonpaged Pool будет выровнено по линии кеша.
|
NonPagedPooMustSucceed
|
Используется
в специальных случаях драйверами, необходимыми для загрузки системы.
|
NonPagedPoolCacheAlignedMustSucceed |
PagedPool
|
Обычное
выделение памяти из Paged Pool.
|
PagedPoolCacheAligned
|
Выделение
памяти из Paged Pool будет выровнено по линии кеша.
|
VOID ExFreePool(IN PVOID address);
PVOID MmAllocateNonCachedMemory(IN ULONG NumberOfBytes);
VOID MmFreeNonCachedMemory( IN PVOID BaseAddress,
IN ULONG NumberOfBytes); PVOID MmAllocateContiguousMemory(IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS HighestAcceptableAddress); VOID MmFreeContiguousMemory(IN
PVOID BaseAddress);
Список заранее выделенных блоков памяти (Lookaside List)
Во многих случаях, выделение и освобождение временного
буфера памяти должно происходить очень часто, для уменьшения накладных
расходов служит Lookaside List - список заранее выделенных блоков памяти
фиксированного размера.
Первоначально, память выделяется только под небольшой заголовок со служебной
информацией. При каждом запросе на выделение памяти проверяется, есть
ли в списке свободные блоки. Если их нет - они выделяются из выгружаемой
или невыгружаемой памяти. Если есть, то помечаются, как используемые и
выдаются для использования.
VOID ExInitializeNPagedLookasideList(
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate OPTIONAL,
IN PFREE_FUNCTION Free OPTIONAL,
IN ULONG Flags,
IN ULONG Size,
IN ULONG Tag,
IN USHORT Depth ); . VOID ExInitializePagedLookasideList(
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate OPTIONAL,
IN PFREE_FUNCTION Free OPTIONAL,
IN ULONG Flags,
IN ULONG Size,
IN ULONG Tag,
IN USHORT Depth );
PVOID ExAllocateFromNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside)
; PVOID ExAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside);
VOID ExFreeToNPagedLookasideList(
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PVOID Entry); VOID ExFreeToPagedLookasideList(
IN PPAGED_LOOKASIDE_LIST .Lookaside,
IN PVOID Entry);
VOID ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside);
VOID ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside) ;
Пространства ввода/вывода и отображение памяти устройств
Смотри раздел «Типы адресов в NT».
BOOLEAN HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress); PVOID MmMapIoSpace(IN PHYSICAL_ADDRESS
PhysicalAddress,
IN ULONG NumberOfBytes,
IN BOOLEAN CacheEnable); VOID MmUnmapIoSpace(IN PVOID BaseAddress,
IN ULONG NumberOfBytes);
Управление памятью и MDL
BOOLEAN MmIsAddressValid(IN PVOID VirtualAddress )/ VOID
MmProbeAndLockPages
(IN OUT PMDL Mdl,
IN KPROCESSOR_MODE AccessMode,
IN LOCK_OPERATION Operation); PVOID MmGetSystemAddressForMdl(IN PMDL Mdl)
MmGetPhysicalAddress(IN PVOID BaseAddress); VOID MmUnlockPages(IN PMDL
mdl) ;
PMDL loAllocateMdl(IN PVOID VirtualAddress,
IN ULONG Length,
IN BOOLEAN SecondaryBuffer,
IN BOOLEAN ChargeQuota,
IN OUT PIRP Irp) ;
VOID MmPrepareMdlForReuse(IN PMDL Mdl); VOID IoFreeMdl(IN PMDL Mdl);
|