Количество методов управления памятью windows xp

Управление памятью в ядре Windows XP — Архив WASM.RU

Для начала нечто вроде вступления. Статья рассчитана на тех, кто уже работал с...

Управление памятью в ядре Windows XP

Дата публикации 17 янв 2008

Управление памятью в ядре Windows XP — Архив WASM.RU

Для начала нечто вроде вступления. Статья рассчитана на тех, кто уже работал с памятью в режиме ядра и отличает MmProbeAndLockPages от MmMapLockedPagesSpecifyCache, а так же знаком с основами устройства управления памятью у процессора — каталоги страниц (PDE), таблицы страниц (PTE), исключение ошибки страницы (#PF). Для исправления первого упущения рекомендуется сначала прочитать соответствующие статьи Four-F (http://www.wasm.ru/series.php?sid=9, части 6 и 9), для исправления второго — статьи цикла BrokenSword «Процессор Intel в защищенном режиме» (http://www.wasm.ru/series.php?sid=20, части 6 и 7, кстати, в части 7 есть ошибка в картинке — вместо картинки для PDE 4M страниц представлена картинка для PDE 4K страниц).

I. Устройство PDE/PTE, невалидные PTE

Рассмотрим сначала как в Windows используются поля PTE, которые помечены Intel как доступные программному обеспечению операционной системы (Avail.)
Эти три бита операционная система Windows использует следующим образом (структуры при выключенном и включенном PAE соответственно):

  1. typedef struct _MMPTE_HARDWARE {
  2.     ULONG CopyOnWrite : 1; // software field
  3.     ULONG Prototype : 1;   // software field
  4.     ULONG reserved : 1;    // software field
  5.     ULONG PageFrameNumber : 20;
  6. } MMPTE_HARDWARE, *PMMPTE_HARDWARE;
  7. typedef struct _MMPTE_HARDWARE_PAE {
  8.     ULONGLONG WriteThrough : 1;
  9.     ULONGLONG CacheDisable : 1;
  10.     ULONGLONG CopyOnWrite : 1; // software field
  11.     ULONGLONG Prototype : 1;   // software field
  12.     ULONGLONG reserved0 : 1;  // software field
  13.     ULONGLONG PageFrameNumber : 24;
  14.     ULONGLONG reserved1 : 28;  // software field
  15. } MMPTE_HARDWARE_PAE, *PMMPTE_HARDWARE_PAE;

Комментариями помечены такие поля.

Поле CopyOnWrite означает, является ли страница копируемой при записи. Такие страницы с пользовательской стороны задаются атрибутом PAGE_WRITECOPY или PAGE_EXECUTE_WRITECOPY и означают, что процессу будет выделена личная копия страницы при попытке записи в неё. Остальные будут использовать публичную не модифицированную копию.
Поле Prototype для валидного PTE означает, что это т.н. прототипный PTE, используемый для разделения памяти между процессами с помощью механизма проецированных в память файлов (Memory Mapped Files, MMF, см. документацию на Win32 API CreateFileMapping, OpenFileMapping, MapViewOfFile(Ex))
Поле reserved для валидного PTE не используется, для невалидного PTE этот бит называется Transition и установлен, когда PTE считается переходным.

Не буду рассказывать про аппаратное управление памятью и остальные поля структур PDE/PTE: об этом неплохо писали уже не один десяток раз. Последующее же повествование пойдет про формат тех PTE, которые использует Windows при флаге Valid = 0, или про недействительные (невалидные) PTE.

  • Paged out PTE (выгруженные PTE) — невалидный PTE, описывающий страницу, выгруженную в файл подкачки. По первому требованию она вновь будет считана и включена в рабочий набор. PTE описывается структурой
    1. typedef struct _MMPTE_SOFTWARE {

    А при включенном PAE такой:

    1. typedef struct _MMPTE_SOFTWARE_PAE {
    2.     ULONGLONG PageFileLow : 4;
    3.     ULONGLONG Protection : 5;
    4.     ULONGLONG Transition : 1;
    5.     ULONGLONG PageFileHigh : 32;

    При этом
    Valid = 0
    PageFileLow содержит номер страничного файла (которых, как нетрудно догадаться, максимально может быть 16 штук)
    Protection, соответственно, атрибуты доступа на страницу, задается в виде констант MM_*:

    1. #define MM_ZERO_ACCESS         0  // this value is not used.
    2. #define MM_EXECUTE_READ        3
    3. #define MM_READWRITE           4  // bit 2 is set if this is writable.
    4. #define MM_EXECUTE_READWRITE   6
    5. #define MM_EXECUTE_WRITECOPY   7
    6. #define MM_NOACCESS         MM_DECOMMIT|MM_NOCACHE

    Prototype = 0
    Transition = 0
    PageFileHigh — номер страницы в страничном файле (о страничном файле и подкачке далее)

  • Demand zero PTE (обнуляемые по требованию PTE) — невалидный PTE, описывающий страницу, которой еще нет в рабочем наборе, но по обращению она должна быть выделена либо из списка обнуленных страниц, либо из списка свободных страниц, обнулена и добавлена в рабочий набор. Описывается аналогично выгруженному PTE за тем исключением, что PageFileHigh = 0.
  • Prototype PTE (прототипные PTE) — невалидные PTE, которые описывают страницы, разделяемые несколькими процессами, например, спроецированные в память файлы. Точнее, такие PTE создаются в одном экземпляре и не включаются в списки PDE, а в списках PDE процесса располагаются следующие невалидные PTE, ссылающиеся на прототипные PTE, соответственно их версии для систем без PAE и с PAE:
    1. typedef struct _MMPTE_PROTOTYPE {
    2.     ULONG ProtoAddressLow : 7;
    3.     ULONG ProtoAddressHigh : 21;
    4. typedef struct _MMPTE_PROTOTYPE_PAE {
    5.     ULONGLONG Protection : 5;
    6.     ULONGLONG ProtoAddress: 32;

    При этом:
    Valid = 0
    ProtoAddress (ProtoAddressLow/ProtoAddressHigh) содержат ссылку на прототипный PTE, описывающий разделяемую страницу.
    Prototype = 1
    Protection содержит атрибуты защиты страницы (MM_*)
    ReadOnly установлен, если страница должна только читаться. Игнорируется при загрузке образов в пространство сеанса — загрузчику позволяется писать в такие страницы в целях обработки импортов или расставления релоков.
    WhichPool назначение этого поля мне неизвестно..

  • Transition PTE (переходные PTE) — невалидные PTE, описывающие страницу, которая находится в списке Standby, Modified или ModifiedNoWrite страниц (об этих списках далее). При обращении страница возвращается в рабочий набор. Описываются следующими структурами:
    1. typedef struct _MMPTE_TRANSITION {
    2.     ULONG PageFrameNumber : 20;
    3. typedef struct _MMPTE_TRANSITION_PAE {
    4.     ULONGLONG WriteThrough : 1;
    5.     ULONGLONG CacheDisable : 1;
    6.     ULONGLONG Protection : 5;
    7.     ULONGLONG Transition : 1;
    8.     ULONGLONG PageFrameNumber : 24;

    При этом:
    Valid = 0
    Prototype = 0
    Transition = 1
    Назначение остальных полей аналогично валидному PTE

II. Обработка ошибок страниц

Когда процессор сталкивается с невалидным PTE, генерируется исключение ошибки страницы (#PF, Page Fault). В Windows обработчик _KiTrap0E вызывает MmAccessFault() для обработки исключения, которая после некоторого числа проверок вызывает MiDispatchFault, если страница должна быть разрешена успешно.

MiDispatchFault вызывает одну из следующих функций для разрешения ошибки страницы:

  • MiResolveProtoPteFault вызывается при ошибке страницы на PTE c флагом Prototype=1
    Она исследует прототипный PTE, на который указывает сбойный PTE и:
    1. Если прототипный PTE тоже имеет флаг Prototype, значит это разделяемые страницы проецированного в память файла. Вызывается MiResolveMappedFileFault.
    2. Если прототипный PTE имеет флаг Transition, то значит, что это переходный PTE, его страница находится в списке модифицированных или простаивающих страниц. Попала она туда в результате усечения рабочего набора. Вызывается MiResolveTransitionFault.
    3. Если у прототипного PTE Transition==0 && Prototype==0 && PageFileHigh==0, то это demand-zero PTE. Вызывается MiResolveDemandZeroFault.
    4. Если у прототипного PTE Transition==0 && Prototype==0 && PageFileHigh!=0, то страница выгружена в своп. Вызывается MiResolvePageFileFault.
  • MiResolveTransitionFault вызывается, когда сбойный PTE имеет флаг Transition=1, либо если он указывает на прототипный PTE, имеющий флаг Transition.
    Поскольку страницы в этом состоянии оказываются в результате усечения рабочего набора или других обстоятельств, когда понадобились физические страницы, то разрешение такой ошибки страницы должно заключаться в возвращении страницы в рабочий набор. Поскольку страница еще не выгружена на диск, то сделать это очень просто — нужно лишь записать валидный PTE на место недействительного.
    Например, в состояние Transition как раз и переводит страницы функция MmTrimAllSystemPagableMemory(0), но о ней подробнее далее в части статьи, посвященную подкачке.
  • MiResolveDemandZeroFault вызван при обработке ошибки страницы, обнуляемой по требованию. Если запрос был из пользовательского режима, тогда идет попытка выделения физической страницы из списка обнуленных страниц (о поддерживаемых списках физических страниц далее). Если это не удается, выделяется свободная страница и обнуляется. При запросе из режима ядра обнуление не форсируется при выделении страницы из списка свободных страниц. Для обнуления используются зарезервированные системные PTE или гиперпространство.
  • MiResolvePageFileFault вызывается при обработке ошибки страницы, которая была выгружена в файл подкачки. Инициируется операция чтения файла подкачки за счет возвращения статуса STATUS_ISSUE_PAGING_IO, страницы читаются из файла подкачки кластерами для снижения числа ошибок страниц.
    Когда MiDispatchFault получает статус STATUS_ISSUE_PAGING_IO, она выполняет операцию чтения страниц с помощью функции IoPageRead, которая производит создание обычного IRP для операции IRP_MJ_READ, но ставит в нем специальный флаг IRP_PAGING_IO. Страница выбирается из списка свободных или обнуленных страниц.

  • MiResolveMappedFileFault вызывается из MiResolveProtoPteFault когда Prototype==1 у прототипного PTE. Тогда PTE трактуется следующим образом (варианты без PAE и с PAE):
    1. typedef struct _MMPTE_SUBSECTION {
    2.     ULONG SubsectionAddressLow : 4;
    3.     ULONG SubsectionAddressHigh : 20;
    4. typedef struct _MMPTE_SUBSECTION {
    5.     ULONGLONG Protection : 5;
    6.     ULONGLONG SubsectionAddress : 32;

    Он содержит адрес объекта SUBSECTION, поддерживающего спроецированный файл. Например, в SUBSECTION::ControlArea->FilePointer хранится FILE_OBJECT файла.

III. Управление физической памятью
Физическая память в системе описывается определенными структурами режима ядра. Они необходимы для поддержания списка свободных и занятых страниц, для удовлетворения аллокаций и других операций с памятью. Для начала рассмотрим, какие же основные части ядра отвечают за описание и распределение физической памяти системы.
Первой структурой, на которую мы обратим внимание, будет MmPhysicalMemoryDescriptor, имеющую описание:

  1. typedef struct _PHYSICAL_MEMORY_RUN {
  2. } PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN;
  3. typedef struct _PHYSICAL_MEMORY_DESCRIPTOR {
  4.     PFN_NUMBER NumberOfPages;
  5.     PHYSICAL_MEMORY_RUN Run[1];
  6. } PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR;
  7. PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryDescriptor;

Переменная ядра MmPhysicalMemoryDescriptor описывает всю доступную и пригодную для использования физическую память в системе и инициализируется при загрузке.

Ядро поддерживает шесть списков страниц (из восьми возможных состояний), в которых размещаются практически все физические страницы, разве что за исключением тех, что используются самим менеджером памяти. Списки страниц поддерживаются указателями u1.Flink и u2.Blink в структуре MMPFN (о ней далее).
Это списки:

  • ZeroedPageList — Список обнуленных страниц, которые можно выдавать по запросу из пользовательского кода. В фоновом режиме работает поток MmZeroPageThread (в него переходит первичный поток KiSystemStartup после всей инициализации) и занимается обнулением свободных страниц с перемещением их в этот список. При запросе страницы пользовательским кодом это наиболее приоритетный список, откуда может быть вынута страница.
  • FreePageList — список свободных страниц. Они могут быть переданы пользоваелю после обнуления (поток либо сигналит событие MmZeroingPageEvent, тогда страницу обнуляет поток обнуления страниц MmZeroPageThread, либо в некоторых исключительных случаях обнуляет самостоятельно — например при обработке #PF на PTE типа demand-zero. В этом случае передача страницы потоку обнуления повлечет за собой дополнительные потери времени), в запросах от пользователя это второй по приоритету список после ZeroedPageList.
  • StandbyPageList — список простаивающих страниц. Эти страницы раньше входили в рабочий набор (процесса или системы), но в последствии были удалены из него. Страница не была изменена с последней записи на диск, PTE, ссылающийся на такую страницу, находится в переходном (transition) состоянии и страница может быть использована для удовлетворения запроса на выделение памяти, но после просмотра списков обнуленных и свободных страниц. ( В Windows 2003 есть 8 подсписков, поддерживающих простаивающие страницы, по приоритетам, они описаны в массиве MmStandbyPageListByPriority[]. В Windows XP и ниже список один)
  • ModifiedPageList — список модифицированных страниц, они тоже раньше входили в рабочий набор, но в последствии были удалены из него в результате сокращения рабочих наборов по какой-либо причине. Страницы были изменены с момента последней записи на диск и должны быть записаны в файл подкачки. PTE все еще ссылается на страницу, но недействителен и находится в состоянии transition.
  • ModifiedNoWritePageList — список модифицированных, но не записываемых страниц. Аналогично предыдущему, но страница не должна быть записана на диск.
  • BadPageList — список страниц, которые были помечены менеджером памяти плохими по каким-либо причинам. Они не должны быть использованы. Например, поток обнуления страниц временно помечает страницы плохими, когда ищет область из страниц, ждущих обнуления, чтобы они не были вдруг переданы какому-нибудь процессу по запросу выделения продолжительного региона памяти (MmAllocateContiguousMemory). PTE не должны ссылаться на такую страницу.

Состояние страниц, не являющиеся списками:

  • ActiveAndValid — страница активная и действительная, не входит ни в один список. Такие страницы являются частью рабочего набора или не входят ни в один рабочий набор и являются частью неподкачиваемой памяти системы. На них ссылаются действительные PTE.
  • TransitionPage — временное состояние страницы на время ожидания операции ввода-вывода.

Указатели на списки хранит переменная ядра MmPageLocationList[], содержимое которой объявлено следующим образом:

  1. PMMPFNLIST MmPageLocationList[8] =
  2.   &MmModifiedNoWritePageListHead,

Есть два важных потока, оперирующих списками страниц — поток обнуления страниц и поток записи модифицированных страниц.

  • Поток обнуления страниц. В него KiSystemStartup переходит после инициализации всех компонентов системы и запуска менеджера сессий smss. Он занимается тем, что в цикле ожидает события MmZeroingPageEvent. Когда оно наступает (а наступает оно при наличии в системе достаточного количества свободных страниц, чтобы поток обнуления мог их стереть), захватывается спин-блокировка базы данных фреймов (PFN Database), выделяется страница из списка свободных страниц, проецируется в гиперпространство и обнуляется, после чего включается в список обнуленных страниц и цикл повторяется.
  • Поток записи модифицированных страниц. После старта подсистемы управления памятью MmInitSystem() создает через PsCreateSystemThread поток MiModifiedPageWriter, который стартует второй вспомогательный поток MiMappedPageWriter, а сам переходит в MiModifiedPageWriterWorker.
    Основной функцией выгрузки страниц в своп-файл является MiGatherMappedPages, о выгрузке будет рассказано далее в следующей части статьи.

MmPfnDatabase.
MmPfnDatabase — это массив структур MMPFN, описывающих каждую физическую страницу в системе. Это, пожалуй, второй по важности объект, после массивов PDE/PTE, которые поддерживают низкоуровневые операции с памятью. В списках PFN хранится информация о конкретной физической странице.
Схематично MMPFN представляется в следующем виде (полное объявлеие прилагается к исходникам к статье, в том числе и для других версий ОС — Windows 2000, Windows 2003 Server):

  1.         PFN_NUMBER Flink;             // Used if (u3.e1.PageLocation < ActiveAndValid)
  2.         WSLE_NUMBER WsIndex;          // Used if (u3.e1.PageLocation == ActiveAndValid)
  3.         PKEVENT Event;                // Used if (u3.e1.PageLocation == TransitionPage)
  4.         NTSTATUS ReadStatus;          // Used if (u4.InPageError == 1)
  5.         PFN_NUMBER Blink;             // Used if (u3.e1.PageLocation < ActiveAndValid)
  6.         ULONG ShareCount;             // Used if (u3.e1.PageLocation >= ActiveAndValid)
  7.         ULONG SecondaryColorFlink;    // Used if (u3.e1.PageLocation == FreePageList or == ZeroedPageList)
  8.             ULONG ReadInProgress : 1;
  9.             ULONG WriteInProgress : 1;
  10.             ULONG RemovalRequested : 1;
  11.             ULONG CacheAttribute : 2;
  12.             ULONG ReferenceCount : 16;
  13.             ULONG VerifierAllocation : 1;

Элементы u1.Flink / u2.Blink поддерживают связанность шести списков страниц, про которые говорилось выше, используются, когда u3.e1.PageLocation < ActiveAndValid.
Если u3.e1.PageLocation >= ActiveAndValid, тогда второе объединение трактуется как u2.ShareCount и содержит счетчик числа пользователей — количество PTE, ссылающихся на эту страницу. Для страниц, содержащих массивы PTE, содержит число действительных PTE на странице.
Если u3.e1.PageLocation == ActiveAndValid, u1 трактуется как u1.WsIndex — индекс страницы в рабочем наборе (или 0 если страница в неподкачиваемой области памяти).
Если u3.e1.PageLocation == TransitionPage, u1 трактуется как u1.Event — адрес объекта «событие», на котором будет ожидать менеджер памяти для разрешения доступа на страницу.
Если u4.InPageError == 1, то u1 трактуется как ReadStatus и содержит статус ошибки чтения.

ReferenceCount содержит счетчик ссылок действительных PTE на эту страницу или использования ее внутри менеджера памяти (например, во время записи страницы на диск, счетчик ссылок увеличивается на единицу). Он всегда >= ShareCount
PteAddress содержит обратную ссылку на PTE, который указывает на эту физическую cтраницу. Младший бит означает, что PFN удаляется.
OriginalPte содержит оригинальный PTE, используемый для восстановления его в случае выгрузки страницы.
u4.PteFrame — номер PTE, поддерживающего страницу, где находится текущая структура MMPFN.
Кроме того объединение u4 содержит еще и следующие дополнительные флаги:

  • InPageError — показывает, что при чтении страницы с диска произошла ошибка. u1.ReadStatus хранит статус этой ошибки.
  • VerifierAllocation устанавливается в единицу для аллокаций, защищаемых Driver Verifier.
  • AweAllocation устанавливается в единицу для Address Windowing Extension
  • Назначение поля LockCharged и одноименного поля MMPFNENTRY мне, к сожалению, не известно. Если кто знает — поделитесь.
  • KernelStack, видимо, устанавливается в единицу для страниц, принадлежащих стеку ядра.

Если страница находится в списке обнуленных или простаивающих страниц, второе объединение трактуется как указатель, связывающий списки обнуленных или свободных страниц по вторичному цвету (т.н. Secondary Color). Различие по цвету делается по следующей причине: количество цветов устанавливается в количество страниц, которые может вместить в себя кеш-память второго уровня процессора и различие делается, чтобы два соседних выделения памяти не использовали страницы одного цвета для правильного использования кеша.

Объединение u3, фактически, содержит флаги данного PFN. Рассмотрим что же они означают:

  • Modified. Установлен для подкачиваемых или спроецированных с диска страниц, что ее содержимое было изменено и должно быть сброшено на диск.
  • ReadInProgress, он же StartOfAllocation
  • WriteInProgress, он же EndOfAllocation
  • PrototypePte, он же LargeSessionAllocation
    Для неподкачиваемых системных адресов эти три поля трактуется как StartOfAllocation, EndOfAllocation и LargeSessionAllocation и обозначают следующее:

    • StartOfAllocation установлено в 1, если эта страница является началом неподкачиваемого пула.
    • EndOfAllocation установлено в 1, если эта страница является концом неподкачиваемого пула.
    • LargeSessionAllocation установлено в 1 для больших аллокаций в пространстве сессии.

    Для подкачиваемых адресов эти поля означают следующее:

    • ReadInProgress установлен, пока страница находится в процессе чтения с диска
    • WriteInProgress установлен, пока страница записывается на диск
    • PrototypePte установлен, когда PTE, который ссылается на эту PFN, является прототипным.
  • PageColor, он же иногда называемый Primary Page Color, или цвет страницы. Используется на некоторых платформах для равномерного распределения списков страниц (аллокации вида MiRemoveAnyPage выдаются страницу каждый раз из другого списка другого цвета и несколько списков, поддерживающих, например, свободные страницы, расходуются равномерно). В x86 и x64 используется всего один цвет страниц и это поле всегда равно нулю.
    Не путать с Secondary Color, который используется для равномерного распределения страниц по кешу второго уровня и используется в функциях MiRemoveZeroPage, MiRemoveAnyPage и др. Кроме простых списков свободных и обнуленных страниц так же поддерживаются списки свободных и обнуленных страниц по цвету — MmFreePagesByColor[список][SecondaryColor], где _список_ — это ZeroedPageList или FreePageList. Списки поддерживаются вместе с общими списками свободных и обнуленных страниц, при обнаружении несоответствия генерируется синий экран PFN_LIST_CORRUPT.
  • PageLocation — тип страницы (как раз один из восьми вышеперечисленных от ZeroedPageList до TransitionPage)
  • RemovalRequested — этим битом помечаются страницы, запрошенные к удалению. После уменьшения их счетчика ссылок до нуля, PTE станет недействительным переходным, а страница попадет в список плохих (BadPageList)
  • CacheAttribute — атрибут кеширования страницы. MmNonCached или MmCached.
  • Rom — новшество WinXP: физическая страница доступна только для чтения.
  • ParityError — на странице произошла ошибка честности

Лучше усвоить написанное поможет пример, содержащийся в приложении к статье. В примере драйвер, который показывает доступные Memory Runs и демонстрирует обращение с PDE/PTE/PFN. Код примера хорошо откомментирован и, с учетом материала статьи, не должен вызвать вопросов.

IV. Управление виртуальной памятью — файл подкачки

Однако размещать все данные постоянно в физической памяти невыгодно — к каким-то данным обращения происходят редко, к каким-то часто, к тому иногда требуются объемы памяти большие, чем доступно физической памяти в системе. Поэтому во всех современных ОС реализован механизм подкачки страниц. Называется он по-разному — выгрузка, подкачка, своп. В Windows этот механизм представляет собой часть менеджера памяти, управляющего подкачкой, и максимально до 16 различных страничных файлов (paging files в терминологии Windows). В Windows есть подкачиваемая и неподкачиваемая память, соответственно, они могут и не могут быть выгружены на диск. Подкачиваемую память в ядре можно выделить из пула подкачиваемой памяти, неподкачиваемую — соответственно из пула неподкачиваемой (для небольших аллокаций). В пользовательском режиме память обычно подкачиваемая, если только она не была заблокирована в рабочем наборе с помощью вызова VirtualLock.
Страничные файлы в ядре Windows представлены переменной ядра MmPagingFile[MAX_PAGE_FILES] (максималное число страничных файлов, как можно было догадаться еще в самом начале по размеру поля номера страницы в страничном файле в 4 бита, составляет 16 штук). Каждый страничный файл в этом массиве представлен указателем на структуру вида:

  1. typedef struct _MMPAGING_FILE {
  2.     PVOID Entry[MM_PAGING_FILE_MDLS];
  3.     UNICODE_STRING PageFileName;
  4. } MMPAGING_FILE, *PMMPAGING_FILE;
  • Size — текущий размер файла подкачки (стр.)
  • MaximumSize — максимальный размер файла подкачки (стр.)
  • MinimumSize — минимальный размер файла подкачки (стр.)
  • FreeSpace — число свободных страниц
  • CurrentUsage — число занятых страниц. Всегда верна формула Size = FreeSpace+CurrentUsage+1 (первая страница не используется)
  • PeakUsage — пиковая нагрузка на файл подкачки
  • Hint, HighestPage, HintSetToZero — [назначение неизвестно]
  • Entry — массив из двух указателей на блоки MMMOD_WRITER_MDL_ENTRY, используемые потоком записи модифицированных страниц.
  • Bitmap — битовая карта RTL_BITMAP занятости страниц в файле подкачки.
  • File — объект «файл» файловой системы, используемый для чтения/записи в файл подкачки
  • PageFileName — имя файла подкачки, например, ??C:pagefile.sys
  • PageFileNumber — номер файла подкачки
  • Extended — флаг, предположительно указывающий на то, расширялся ли файл подкачки когда-либо с момента создания
  • BootPartition — флаг, указывающий на то, располагается ли файл подкачки на загрузочном разделе. Если нет ни одного страничного файла, размещенного на загрузочном разделе, то во время BSoD аварийный дамп записываться не будет.
  • FileHandle — хендл файла подкачки.

В приложении к статье есть откомментированный пример с выводом полей структуры MmPagingFile[0] рабочей системы.

Когда системе нужна страница, а свободных страниц осталось мало, происходит усечение рабочих наборов процессов (оно происходит и по другим причинам, это лишь одна из них). Допустим, что усечение рабочих наборов было инициировано функцией MmTrimAllSystemPagableMemory(0). Во время усечения рабочих наборов, PTE страниц переводятся в состояние Transition, счетчик ссылок Pfn->u3.e2.ReferenceCount уменьшеается на 1 (это выполняет функция MiDecrementReferenceCount). Если счетчик ссылок достиг нуля, сами страницы заносятся в списки StandbyPageList или ModifiedPageList, в зависимости от Pfn->u3.e1.Modified. Страницы из списка StandbyPageList могут быть использованы сразу, как только потребуется — для этого достаточно лишь перевести PTE в состояние Paged-Out. Страницы из списка ModifiedPageList должны быть сперва записаны потоком записи модифицированных страниц на диск, а уж после чего они переводятся в StandbyPageList и могут быть использованы (за выгрузку отвечает функция MiGatherPagefilePages()).

Псевдокод снятия страницы из рабочего набора (сильно обрезанный код MiEliminateWorkingSetEntry и вызываемых из нее функций):

  1. PageFrameNumber = PointerPte->u.Hard.PageFrameNumber;
  2. if( Pfn->u3.e1.PrototypePte == 0)
  3.     // Приватная страница, сделать переходной.
  4.     MI_ZERO_WSINDEX (Pfn);  // Pfn->u1.WsIndex = 0;
  5.     // Следующий макрос делает это:
  6.     // TempPte.u.Soft.Valid = 0;
  7.     // TempPte.u.Soft.Transition = 1;
  8.     // TempPte.u.Soft.Prototype = 0;
  9.     // TempPte.u.Trans.Protection = PROTECT;
  10.     MI_MAKE_VALID_PTE_TRANSITION (TempPte,
  11.                                   Pfn->OriginalPte.u.Soft.Protection);
  12.     // Этот вызов на самом деле заменяет текущий PTE на TempPte и очищает буфера
  13.     // ассоциативной трансляции
  14.     // ( *PointerPte = TempPte );
  15.     PreviousPte.u.Flush = KeFlushSingleTb(
  16.                                     Wsle[WorkingSetIndex].u1.VirtualAddress,
  17.                                     (Wsle == MmSystemCacheWsle),
  18.     // Декремент счетчика использования. Если он стал равен нулю, страница переводится в переходное состояние
  19.     // и уменьшается на единицу счетчик ссылок.
  20.     // MiDecrementShareCount()
  21.     if( Pfn->u2.ShareCount == 0 )
  22.         if( Pfn->u3.e1.PrototypePte == 1 )
  23.             // … Дополнительная обработка прототипных PTE …
  24.         Pfn->u3.e1.PageLocation = TransitionPage;
  25.         // Уменьшаем на 1 счетчик ссылок. Если он тоже стал равен нулю, перемещаем
  26.         //  страницу в список модифицированных или простаивающих страниц, либо полностью удаляем
  27.         // (помещая в список плохих страниц) в зависимости от MI_IS_PFN_DELETED() и RemovalRequested.
  28.         // MiDecrementReferenceCount()
  29.         Pfn->u3.e2.ReferenceCount -= 1;
  30.         if( Pfn->u3.e2.ReferenceCount == 0 )
  31.             if( MI_IS_PFN_DELETED(Pfn) )
  32.                 // PTE больше не ссылаются на эту страницу. Переместить ее в список свободных либо удалить, если нужно.
  33.                 MiReleasePageFileSpace (Pfn->OriginalPte);
  34.                 if( Pfn->u3.e1.RemovalRequested == 1 )
  35.                     // Страница помечена к удалению. Перемещаем ее в список плохих страниц. Она не будет использована,
  36.                     // пока кто-либо не удалит ее из этого списка.
  37.                     MiInsertPageInList (MmPageLocationList[BadPageList],
  38.                     // Помещаем страницу в список свободных
  39.                     MiInsertPageInList (MmPageLocationList[FreePageList],
  40.             if( Pfn->u3.e1.Modified == 1 )
  41.                 // Страница модифицирована. Помещаем в список модифицированных страниц,
  42.                 // поток записи модифицированных страниц запишет ее на диск.
  43.                 MiInsertPageList (MmPageLocationList[ModfifiedPageList], PageFrameIndex);
  44.                 if (Pfn->u3.e1.RemovalRequested == 1)
  45.                     // Удалить страницу, но оставить ее состояние как простаивающее.
  46.                     Pfn->u3.e1.Location = StandbyPageList;
  47.                     MiRestoreTransitionPte (PageFrameIndex);
  48.                     MiInsertPageInList (MmPageLocationList[BadPageList],
  49.                 // Помещаем страницу в список простаивающих страниц.
  50.                     MiInsertPageInList (MmPageLocationList[StandbyPageList],
  51.                     MiInsertStandbyListAtFront (PageFrameNumber);

В приложении к статье есть программа с исходными кодами для демонстрации усечения рабочих наборов из пользовательского режима с помощью вызова SetProcessWorkingSetSize(hProcess, -1, -1).

Напротив, когда поток обращается к странице, которая была удалена из рабочего набора, происходит ошибка страницы. К страничным файлам относятся два типа PTE: Transition и Paged-Out. Если страница была удалена из рабочего набора, но еще не была записана на диск или ей вообще не нужно быть записанной на диск и она ЕЩЕ НАХОДИТСЯ в физической памяти (состояние Transition PTE), то вызывается MiResolveTransitionFault() и PTE просто переводится в состояние Valid с соответствующей корректировкой MMPFN и удалением страницы из списка простаивающих или модифицированных страниц. Если страница уже была записана на диск, либо ей не нужно было быть записанной на диск и ее уже использовали для каких-то других целей (состояние Paged-Out PTE), то вызывается MiResolvePageFileFault() и инициируется операция чтения страницы из файла подкачки со снятием соответствующего бита в битовой карте.
Псевдокод разрешения Transition Fault (обрезанный код MiResolveTransitionFault):

  1. if( Pfn->u4.InPageError )
  2.     return Pfn->u1.ReadStatus;  // #PF на странице, чтение которой не удалось.
  3. if (Pfn->u3.e1.ReadInProgress)
  4.     // Повторная ошибка страницы. Если снова у того же потока,
  5.     // то возвращается STATUS_MULTIPLE_FAULT_VIOLATION;
  6.     // Если у другого — тогда ожидаем завершения чтения.
  7. MiUnlinkPageFromList (Pfn);
  8. Pfn->u3.e2.ReferenceCount += 1;
  9. Pfn->u3.e1.PageLocation = ActiveAndValid;
  10. MI_MAKE_TRANSITION_PTE_VALID (TempPte, PointerPte);
  11. MI_WRITE_VALID_PTR (PointerPte, TempPte);
  12. MiAddPageToWorkingSet (…);

Псевдокод загрузки страницы с диска (обрезанный код MiResolvePageFileFault):

  1. // Подготовить параметры для чтения
  2. PageFileNumber = TempPte.u.Soft.PageFileLow;
  3. StartingOffset.QuadPart = TempPte.u.Soft.PageFileHigh << PAGE_SHIFT;
  4. FilePointer = MmPagingFile[PageFileNumber]->File;
  5. // Выбрать свободную страницу
  6. PageColor = (PFN_NUMBER)((MmSystemPageColor++) & MmSecondaryColorMask);
  7. PageFrameIndex = MiRemoveAnyPage( PageColor );
  8. // Скорректировать ее запись в базе данных страниц
  9. Pfn = MI_PFN_ELEMENT (PageFrameIndex);
  10. Pfn->PteAddress = PointerPte;
  11. Pfn->OriginalPte = *PointerPte;
  12. Pfn->u3.e2.ReferenceCount += 1;
  13. Pfn->u3.e1.ReadInProgress = 1;
  14. if( !MI_IS_PAGE_TABLE_ARRESS(PointerPte) )  Pfn->u3.e1.PrototypePte = 1;
  15. Pfn->u4.PteFrame = MiGetPteAddress(PointerPte)->PageFrameNumber;
  16. // Временно перевести страницу в Transition состояние на время чтения
  17. MI_MAKE_TRANSITION_PTE ( TempPte, … );
  18. MI_WRITE_INVALID_PTE (PointerPte, TempPte);
  19. Status = IoPageRead (FilePointer,
  20. if( Status == STATUS_SUCCESS )
  21.     MI_MAKE_TRANSITION_PTE_VALID (TempPte, PointerPte);
  22.     MI_WRITE_VALID_PTE (PointerPte, TempPte);
  23.     MiAddValidPageToWorkingSet (…);

Рабочие наборы
Рабочий набор по определению — это совокупность резидентных страниц процесса (системы). Существуют три вида рабочих наборов:

  • Рабочий набор процесса содержит резидентные страницы, принадлежащие процессу — код, данные процесса и все последующие аллокации пользовательского режима. Хранится в EPROCESS::Vm
  • Рабочий набор системы содержит резидентные подкачиваемые страницы системы. В него входят страницы подкачиваемого кода, данных ядра и драйверов устройств, системного кеша и пула подкачиваемой памяти. Указатель на него хранится в переменной ядра MmSystemCacheWs.
  • Рабочий набор сеанса содержит резидентные страницы сеанса, например, графической подсистемы Windows (win32k.sys). Указатель хранится в MmSessionSpace->Vm.

Когда системе нужны свободные страницы, инициируется операция усечения рабочих наборов — страницы отправляются в списки Standby или Modified, в зависимости от того, была ли запись в них, а PTE переводятся в состояние Transition. Когда страницы окончательно отбираются, то PTE переводятся в состояние Paged-Out (если это были страницы, выгружаемые в файл подкачки) или в Invalid, если это были страницы проецируемого файла.
Когда процесс обращается к странице, то страница либо удаляется из списков Standy/Modified и становится ActiveAndValid, либо инициируется операция загрузки страницы с диска, если она была окончательно выгружена. Если памяти достаточно, процессу позволяется расширить свой рабочий набор и даже превысить максимум для загрузки страницы, иначе для загрузки страницы выгружается какая-то другая, то есть новая страница замещает старую.
Имеется системный поток управления рабочими наборами или т.н. диспетчер баланса. Он ожидает на двух объектах KEVENT, первое из которых срабатывает по таймеру раз в секунду, а второе срабатывает, когда нужно изменить рабочие наборы. Диспетчер настройки баланса так же проверяет ассоциативные списки, регулируя из глубину для оптимальной производительности.

V. Ядерные функции управления памятью
В этой части речь пойдет о некоторых полезных функциях управления памятью в режиме ядра.
Слои функции управления памятью ядра можно разделить следующим образом от низшего уровня к высшему:

  • макросы MI_WRITE_VALID_PTE/MI_WRITE_INVALID_PTE
  • низкоуровневые функции MiResolve..Fault, MiDeletePte и другие функции работы с PDE/PTE, а так же функции работы с MMPFN и списками страниц — MiRemovePageByColor, MiRemoveAnyPage, MiRemoveZeroPage.
  • функции, предоставляемые драйверам для работы с физической памятью: MmAllocatePagesForMdl, MmFreePagesFromMdl, MmAllocateContiguousMemory.
  • функции, предоставляемые драйверам для работы с пулом: ExAllocatePoolWith…, ExFreePoolWith…, MmAllocateContiguousMemory (относится и к предыдущему слою и к этому)

Для пользовательской памяти дело обстоит немного по-другому:

  • макросы MI_WRITE_VALID_PTE/MI_WRITE_INVALID_PTE
  • функции работы с VAD и пользовательской памятью — MiAllocateVad, MiCheckForConflictingVad, и др.
  • функции работы с виртуальной памятью — NtAllocateVirtualMemory, NtFreeVirtualMemory, NtProtectVirtualMemory.

Описывать начнем их от низшего уровня к высшему, сначала для управления памятью ядра, затем пользовательской памятью.

Управление памятью режима ядра

1. макросы MI_WRITE_VALID_PTE/MI_WRITE_INVALID_PTE
Эти макросы используются во всех функциях, которые как-либо затрагивают выделение или освобождение физической (в конечном итоге) памяти. Соответственно, они записывают действительный и недействительный PTE в таблицу страниц процесса.

2. Низкоуровневые функции для работы с PDE/PTE и списками физических страниц
Все это, вообщем то, я уже описывал, когда рассказывал про списки страниц, MMPFN и другое, поэтому приведу лишь прототипы функций с кратким описанием их действий:
PFN_NUMBER FASTCALL MiRemoveAnyPage(IN ULONG PageColor) ; // Выделяет физическую страницу заданного цвета (SecondaryColor) из списков свободных, обнуленных или простаивающих страниц.
PFN_NUMBER FASTCALL MiRemoveZeroPage(IN ULONG PageColor) ; // Выделяет физическую страницу заданного цвета (SecondaryColor) из списка свободных страниц.
VOID MiRemovePageByColor (IN PFN_NUMBER Page, IN ULONG Color); // Выделяет указанную страницу, удаляя ее из списка свободных страниц указанного цвета.

3. Функции, предоставляемые драйверам для работы с физической памятью
PMDL
MmAllocatePagesForMdl(
IN PHYSICAL_ADDRESS LowAddress,
IN PHYSICAL_ADDRESS HighAddress,
IN PHYSICAL_ADDRESS SkipBytes,
IN SIZE_T TotalBytes
);

Эта функция выделяет физические страницы (не обязательно идущие подряд, как это делает, например, MmAllocateContiguousMemory), пробуя выделить страницы общим размером TotalBytes, начиная с физического адреса LowAddress и заканчивая HighAddress, «перешагивая» по SkipBytes.
Просматриваются списки обнуленных, затем свободных страниц. Разумеется, страницы неподкачиваемые. Если страниц не хватает, функция старается выделить столько страниц, сколько возможно.
Возвращаемое значение — Memory Descriptor List (MDL), описывающий выделенные страницы. Они должны быть освобождены соответствующим вызовом MmFreePagesFromMdl и ExFreePool для структуры MDL.
Страницы НЕ спроецированы ни на какие виртуальные адреса, об этом должен позаботиться программист с помощью вызова MmMapLockedPages.

PVOID
MmAllocateContiguousMemory(
IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS HighestAcceptableAddress
);

Функция выделяет физически непрерывную область физических страниц общим размером NumberOfBytes, не выше HighestAcceptableAddress, так же проецируя их в адресное пространство ядра. Сначала она пытается выделить страницы из неподкачиваемого пула, если его не хватает, она начинает просматривать списки свободных и обнуленных страниц, если и их не хватает, то она просматривает страницы из списка простаивающих страниц. Возвращает базовый адрес выделенного участка памяти. Память должна быть освобождена с помощью вызов MmFreeContiguousMemory.

4. функции, предоставляемые драйверам для работы с пулом
Они подробно описаны в статье Four-F, поэтому останавливаться на этом я не буду.

Дополнительные функции управления памятью режима ядра
Из функций контроля ядерной памяти следует, наверное, упомянуть про MmIsAddressValid и MmIsNonPagedSystemAddressValid.
Функция MmIsAddressValid проверяет страницу памяти на то, возникнет ли ошибка страницы при доступе к этому адресу. То есть, другими словами, она проверяет тот факт, что страница уже сейчас находится в физической памяти. Следует отметить, что состояние transition,paged-out,prototype ее не волнуют, поэтому она может использоваться лишь для контроля адресов при высоких IRQL (>=DPC/Dispatch), поскольку при этих IRQL не разрешены ошибки страниц (а если встретится ошибка страницы, будет выброшен синий экран IRQL_NOT_LESS_OR_EQUAL). Если нужно проверять ядерные адреса на доступ при низком IRQL, то, насколько мне известно, нет документированных способов это сделать. Видимо, считается, что драйвер должен знать, какие у него адреса правильные, а какие нет и не пробовать обращаться по неправильным адресам. В приложении к статье имеется написанная мной функция MmIsAddressValidEx, которая проверяет адрес на корректность доступа при низком IRQL, учитывая, что PTE может находиться в недействительном состоянии, но ошибка страницы не вызовет синего экрана или исключения (в программном смысле). С учетом рассказанных мною структур недействительных PTE, разобраться в ее исходном коде будет нетрудно.
Функция MmIsNonPagedSystemAddressValid, почему-то незаслуженно «выброшенная» разработчиками Windows и обозначенная как obsolete, на самом деле тоже полезна. Она на порядок проще, чем MmIsAddressValid (которую, кстати, и рекомендует использовать Microsoft), и всего лишь проверяет то, что переданный ей адрес принадлежит подкачиваемой или неподкачиваемой областям памяти ядра. Адрес не проверяется на корректность, но результат функции вовсе не эквивалентен MmIsAddressValid (в том смысле, что память может быть в пуле подкачиваемой памяти, но может быть как выгружена на диск так и загружена, поэтому возвращенное значение FALSE еще ничего не говорит о том, можно ли обращаться к этой памяти), поэтому я совершенно не понимаю, почему Microsoft сочли ее «obsolete» и не рекомендуют использовать, подсовывая взамен MmIsAddressValid. Использовать MmIsNonPagedSystemAddressValid мы будем, например, в функции вывода MMPFN в приложении, когда потребуется определить, принадлежит ли адрес подкачиваемому пулу (поля MMPFN, как Вы помните, различаются для подкачиваемого и неподкачиваемого пулов).

Управление пользовательской памятью
Для начала стоит заметить, что для управления пользовательской памятью используется дополнительный механизм — Virtual Address Descriptors (VAD), которые описывают проекции секций, а так же выделения памяти через NtAllocateVirtualMemory (VirtualAlloc в Win32 API). Представлены эти VAD в виде дерева, указатель на вершину содержится в поле EPROCESS->VadRoot. Секции можно создавать и проецировать на пользовательские адреса с помощью NtCreateSection, NtMapViewOfSection (Win32API-аналоги у них: CreateFileMapping, MapViewOfFileEx). Адреса памяти могут резервироваться (reserve) и в последствии память по этим адреса может передаваться (commit) процессу. Этим заведует NtAllocateVirtualMemory.

Функции работы с VAD и пользовательской памятью
Элемент VAD представлен следующей структурой:

  1. typedef struct _MMVAD_FLAGS {
  2.     ULONG_PTR CommitCharge : COMMIT_SIZE;
  3.     ULONG_PTR PhysicalMapping : 1;
  4.     ULONG_PTR UserPhysicalPages : 1;
  5.     ULONG_PTR WriteWatch : 1;
  6.     ULONG_PTR Protection : 5;
  7.     ULONG_PTR LargePages : 1;
  8.     ULONG_PTR PrivateMemory : 1;
  9. typedef struct _MMVAD_SHORT {
  10.     struct _MMVAD *LeftChild;
  11.     struct _MMVAD *RightChild;
  12. } MMVAD_SHORT, *PMMVAD_SHORT;

Так же есть структура MMVAD, аналогичная MMVAD_SHORT, но содержащая больше полей и используемая для проецированных файлов (дополнительные поля это PCONTROL_AREA, необходимая для поддержания спроецированных файлов и содержащая такие важные указатели, как PFILE_OBJECT и др; о проекциях файлов, как-нибудь в следующий раз: и так уже 50 килобайт вышло =), а MMVAD_SHORT используется для пользовательских выделений памяти.
Чтобы отличить, какой именно VAD представлен указателем, используется флаг u.VadFlags.PrivateMemory: если он установлен, то это «частная память», то есть обычное выделение памяти. Если сброшен — проекция файла.
Поля StartingVpn и EndingVpn, соответственно, обозначают начальную и конечную виртуальную страницу (Virtual Page Number) описываемой области (для конвертирования виртуального адреса в номер страницы используется MI_VA_TO_VPN, который просто сдвигает виртуальный адрес на PAGE_SHIFT бит вправо).
Поля Parent, LeftChild, RightChild используются для связи дескрипторов виртуальных адресов в дерево.
u.VadFlags содержит некоторые полезные флаги, а именно:

  • CommitCharge. Это поле содержит количество фактически выделенных и переданных страниц процессу, если VAD описывает переданную память, или 0 если описывается зарезервированная память.
  • PhysicalMapping. Этот флаг показывает, что память на самом деле является проекцией физических страниц, созданной с помощью MmMapLockedPages при AccessMode == UserMode.
  • Флаг ImageMap показывает, что VAD описывает загруженный исполняемый модуль (с помощью LoadLibrary и других, в конечном итоге сводящихся к NtCreateSection с SEC_IMAGE).
  • UserPhysicalPages устанавливается при вызове NtAllocateVirtualMemory с MEM_PHYSICAL|MEM_RESERVE, используемом для выделения окна для физических страниц при испольщовании AWE (Address Windowing Extensions).
  • NoChange установлен, когда запрещено менять атрибуты доступа области, описываемой этим VAD. Чтобы создать такую область, используется флаг SEC_NO_CHANGE у NtCreateSection.
  • WriteWatch устанавливается при выделении памяти с флагом MEM_WRITE_WATCH, при этом создается битовая карта страниц, где впоследствии отмечается, на какие страницы была произведена запись. Эту информацию можно получить в последствии через Win32 API GetWriteWatch() и сбросить карту через ResetWriteWatch()
  • Protection — изначальные атрибуты доступа к памяти.
  • LargePages содержит 1 при использовании больших страниц через MEM_LARGE_PAGES. В Windows XP/2000 не поддерживается.
  • MemCommit содержит 1 если память была передана процессу.
  • PrivateMemory, как уже было сказано, отличает MMVAD от MMVAD_SHORT.

Функция MiAllocateVad выделяет VAD для процесса, резервируя переданные ей адреса, а функция MiCheckForConflictingVad (на самом деле макрос, раскрывающийся в вызов функции MiCheckForConflictingNode) проверяет, существуют ли VAD у процесса такие, что описываемая ими область памяти перекрывается с указанными виртуальными адресами. Если это так, возвращается VAD первой конфликтной области, иначе NULL. Функция используется при передаче памяти процессу в NtAllocateVirtualMemory для поиска VAD, соответствующего указанному адресу.
Функция MiInsertVad добавляет VAD в дерево виртуальных дескрипторов адресов процесса и реорганизует его, если это нужно.
Функция MiRemoveVad, соответственно, удаляет и освобождает VAD. Перейдем теперь к функциям, доступным пользовательскому коду и драйверам устройств для управления памятью.

Функция NtAllocateVirtualMemory производит следующие действия:
1) для резервирования адресов вызывается MiCheckForConflictingVad для проверки, не была ли эта область или какая-либо ее часть зарезервированы или использованы другой функцией для работы с памятью (например, проецированием секции) ранее. Если так — возвращает STATUS_CONFLICTING_ADDRESSES.
Далее выделяется VAD функцией MiAllocateVad, заполняются соответствующие поля и VAD добавляется в дерево с помощью MiInsertVad. Если он описывает AWE-вид или включен WriteWatch, тогда еще вызывается MiPhysicalViewInserter.
2) для передачи адресов вызывается MiCheckForConflictingVad, но уже с целью найти соответствующий VAD, созданный при резервировании. Потом соответствующие страницы выставляются в таблице страниц как обнуляемые по требованию, а так же меняются атрибуты защиты, если это необходимо.
NtFreeVirtualMemory производит обратные действия.

На этом я думаю, наконец-то (!), что статью можно завершить.

В приложении к статье можно найти:

  1. программу Working Sets для демонстрации усечения рабочих наборов.
  2. Функции ручной загрузки и выгрузки страницы в файл подкачки. Примечание: очень сырые! Поскольку страница не добавляется в рабочий набор и не удаляется из него, может быть синий экран MEMORY_MANAGEMENT или PFN_LIST_CORRUPT (для выгрузки и загрузки соответственно), поэтому экспериментировать на реальной системе я не советую. Лучше запускать только изучающий и анализирующий код, который не изменяет никаких параметров системы. Это функции MiPageOut и MiLoadBack (префиксы Mi я сам добавил для красоты :smile3:)
  3. Функция вывода в DbgPrint содержимого MMPFN. Это MiPrintPfnForPage.
  4. Функция MmIsAddressValidEx для расширенной проверки доступа к адресам при низком IRQL. Возвращает статус проверки — элемент перечисления
    1. enum VALIDITY_CHECK_STATUS {
    2.     VCS_INVALID = 0,     //  = 0 (FALSE)

    Так же может трактоваться как BOOLEAN, поскольку статус невалидной страницы 0, а все остальные больше нуля.

  5. Комплексный пример драйвера, демонстрирующий все эти функции (ручная загрузка и выгрузка закомментированы).

© Great


archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532


WASM

Сказки про «полезные» оптимизаторы памяти

Организация памяти в Windows XP

   Страничная организация памяти

   Сегментная организация памяти

   Сегментно-страничная организация памяти

Принцип работы менеджера памяти

Фокусы оптимизаторов памяти

Практические примеры

   dRAMatic v 8.1

   Clean RAM 1.21

   FAST Defrag 2.3

   FreeRAM XP Pro 1.52

   Memory Optimizer 2002a

   MemTurbo 2

   RAM Idle Professional 3.4

Выводы

Нас так часто обманывают, что мы к этому уже привыкли и не доверяем никому и ничему. Ложь рекой льется с экранов телевизоров, из уст высокопоставленных чиновников, в центральной прессе то и дело появляются проплаченные заказные статьи с явной неправдой, а уж про ненадлежащую рекламу и говорить не приходится. Вспомним хотя бы страшилки про птичий грипп, которые внезапно возникли и так же неожиданно, подчиняясь чьей-то искусной дирижерской палочке, исчезли. Или про отравленное грузинское и молдавское вино. В результате эти вина исчезли с прилавков магазинов, а вместо них нам предложили довольствоваться дешевым вином из других стран, которое как нельзя лучше соответствует слову «бормотуха». Примеры такого «гуманизма» встречаются на каждом шагу. «Но при чем здесь программное обеспечение и компьютеры?» — спросите вы. Все очень просто: принцип «обмани и получи выгоду» нередко применяется и в области программного обеспечения. Наряду с полезными программами пользователям нередко (причем за деньги) предлагают и откровенные пустышки, которые, по заявлениям производителей, способны в разы увеличить производительность системы. В лучшем случае они не навредят, а в худшем — вместо обещанного увеличения производительности приведут к обратному эффекту. Классическим примером такого рода программ являются оптимизаторы оперативной памяти, которые и будут рассмотрены в настоящей статье.

Принцип, которым руководствуются компании, предлагающие оптимизаторы памяти, достаточно прост и неоригинален. Надо заставить пользователя поверить в чудодейственные возможности утилиты и убедить его, что использование оптимизатора памяти позволит и решить проблему нехватки памяти, и повысить производительность ПК. Сделать это не так уж сложно, особенно если речь идет о неискушенном пользователе. Алгоритм убеждения примерно таков. Прежде всего необходимо убедить пользователя, что операционная система Windows XP далека от идеала. Учитывая постоянную критику в адрес Microsoft, сделать это легко (тем более что в этом есть доля истины), ну а для пущей убедительности можно напомнить о регулярном появлении так называемых заплаток и обновлений к операционной системе. Далее нужно убедить пользователя, что исправить недочеты операционной системы можно с помощью сторонних утилит (факт достаточно спорный, хотя отчасти он соответствует действительности). В качестве примера можно привести множество сторонних утилит (те же дефрагментаторы), которые по некоторым характеристикам лучше встроенных в операционную систему. Ну а если все это «приправить» научными терминами об утечке оперативной памяти, о необходимости ее дефрагментации и о неоптимизированных алгоритмах выделения оперативной памяти процессам (главное при этом — окончательно запудрить мозги специфическими терминами), то необходимость использования сторонних оптимизаторов памяти (наделенных интеллектуальными, продвинутыми алгоритмами слежения за состоянием памяти, позволяющих оптимизировать ее распределение и проводящих в случае необходимости автоматическую дефрагментацию) становится просто очевидным фактом.

На сфабрикованную таким образом утку кто-нибудь да клюнет. Причем, как показывает практика, клюют многие.

Чтобы доказать пользователю необоснованность приведенных выше рассуждений, необходимо сначала рассказать, каким образом операционная система Windows XP распределяет оперативную память.

Организация памяти в Windows XP

В любой момент компьютер выполняет сразу несколько процессов (или задач), каждый из которых располагает своим адресным пространством. Было бы слишком накладно отдавать всю физическую память какой-то одной задаче, тем более что многие из них реально используют только небольшую часть своего адресного пространства. Поэтому необходим механизм разделения небольшой физической памяти между различными задачами. Кроме того, уже давно существует проблема размещения в памяти программ, размер которых превышает размер доступной физической памяти.

Одним из способов разделения физической памяти между различными процессами и размещения в памяти программ, размер которых превышает размер доступной физической памяти, является использование технологии виртуальной памяти (virtual memory), которая впервые была реализована в 1959 году на компьютере «Атлас», разработанном в Манчестерском университете. Однако популярной технология виртуальной памяти стала лишь спустя десятилетия.

Виртуальная память делит физическую память на отдельные блоки и распределяет их между различными задачами. При этом она предусматривает некоторую схему защиты, которая ограничивает задачу теми блоками, которые ей принадлежат. Кроме того, виртуальная память позволяет объединить (с точки зрения программ) физическую оперативную память компьютера и внешнюю память (например, память жесткого диска).

Системы виртуальной памяти можно разделить на три класса:

  • системы с фиксированным размером блоков, называемых страницами,  — страничная организация памяти;
  • системы с переменным размером блоков, называемых сегментами, — сегментная организация памяти;
  • комбинированные системы с сегментно-страничной организацией памяти.

В настоящее время актуально говорить только о сегментно-страничной организации памяти, однако для лучшего понимания этого способа мы рассмотрим также страничную и сегментную организацию памяти.

Страничная организация памяти

В случае страничной организации памяти и виртуальная и физическая память представляются в виде набора неперекрывающихся блоков одинакового размера, называемых страницами. Передача информации (считывание, запись) всегда осуществляется целыми страницами.

При страничной организации виртуальный адрес памяти требуемого элемента задается в виде номера страницы и смещения относительно начала страницы. Любой выполняемый процесс (программа) имеет дело только с виртуальными адресами и не знает физических адресов данных, с которыми работает. Для преобразования виртуальных адресов в физические используются таблицы страниц (page table), размещаемые в оперативной памяти. Важно, что каждому процессу соответствует собственная таблица страниц.

Преобразование логических (виртуальных) адресов в физические происходит следующим образом. Когда какой-либо выполняемый процесс обращается по виртуальному адресу, в котором содержится информация о номере требуемой страницы и смещении в пределах страницы, происходит обращение к таблице страниц этого процесса, в которой каждому номеру страницы поставлен в соответствие физический адрес страницы в памяти.

Таким образом, по номеру страницы определяется физический адрес этой страницы в памяти. Далее с учетом известного смещения в пределах требуемой страницы определяется физический адрес искомого элемента памяти (рис. 1).

Рис. 1. Связь логического и физического адресов при страничной организации памяти

Любой процесс может выполняться только в том случае, если используемые им страницы памяти размещаются в оперативной памяти. При отсутствии запрашиваемой страницы в оперативной памяти возникает исключительная ситуация — страничное нарушение (page fault). Тогда затребованная страница подкачивается из внешней памяти (своп-файла) в свободный страничный кадр физической памяти, а при отсутствии свободных страничных кадров в оперативной памяти первоначально в своп-файл выгружается мало используемая страница памяти.

При страничной организации памяти может возникать проблема ее внутренней фрагментации (внешней фрагментации в данном случае принципиально не существует). Внутренняя фрагментация памяти происходит по причине того, что адресное пространство процесса может занимать только целое число страниц, при этом некоторые страницы заняты не полностью.

Важно отметить, что при страничной организации памяти любому процессу доступна лишь та физическая память, которая ему соответствует, и не доступна память другого процесса, поскольку процесс не имеет возможности адресовать память за пределами своей таблицы страниц, включающей только его собственные страницы.

Сегментная организация памяти

Понятие сегментированной памяти связано с необходимостью разделения хранимых в памяти данных между различными процессами. Именно в этом заключается главное отличие сегментированной организации памяти от страничной.

Участки памяти, хранящие однородные данные, которые доступны нескольким процессам, называются сегментами. Каждый сегмент представляет собой отдельную логическую единицу информации, содержащую совокупность данных или программ и расположенную в адресном пространстве пользователя. Сегменты создаются пользователями, которые могут обращаться к ним по символическому имени. В каждом сегменте устанавливается собственная нумерация слов начиная с нуля.

При сегментной организации памяти каждый сегмент определяется двумя величинами: именем сегмента и смещением. В отличие от страниц, разные сегменты могут иметь различные размеры, причем размер сегмента может меняться динамически.

Точно так же, как и при страничной организации, при сегментной организации памяти для преобразования виртуального адреса требуемого элемента в физический адрес используются таблицы сегментов. В таблице сегментов, помимо физического адреса начала сегмента, содержится также длина сегмента. Преобразование логических адресов в физические происходит следующим образом. Когда выполняемый процесс обращается по виртуальному адресу, происходит обращение к таблице сегментов, что позволяет определить физический адрес требуемого сегмента. Используя информацию о смещении в пределах сегмента, можно определить физический адрес искомого элемента (рис. 2).

Рис. 2. Преобразование логического адреса при сегментной
организации памяти

Сегментно-страничная организация памяти

Сегментная организация памяти в чистом виде не встречается и в этом смысле интересна лишь в теоретическом аспекте. Как уже отмечалось, в операционных системах семейства Windows используется комбинированная сегментно-страничная организация памяти.

При сегментно-страничной организации памяти происходит двухуровневая трансляция виртуального адреса в физический. В этом случае виртуальный адрес состоит из трех полей: номера сегмента виртуальной памяти, номера страницы внутри сегмента и смещения внутри страницы. Соответственно для преобразования виртуальных адресов в физические применяются две таблицы: таблица сегментов, которая связывает номер сегмента с таблицей страниц и называется также таблицей каталогов страниц, и отдельная таблица страниц для каждого сегмента (рис. 3). При преобразовании виртуального адреса элемента в физический адрес первоначально по номеру каталога страниц устанавливается требуемая таблица страниц. Далее с использованием таблицы страниц и номера страницы определяется физический адрес страницы, а зная смещение внутри страницы, можно определить физический адрес искомого элемента.

Рис. 3. Формирование физического адреса при сегментно-страничной организации памяти

Главная особенность сегментно-страничной организации виртуальной памяти заключается в том, что при этом имеется возможность совместно применять одни и те же сегменты данных и программного кода в виртуальной памяти разных процессов, поскольку для совместно используемых сегментов поддерживаются общие таблицы страниц.

Далее мы рассмотрим 32-разрядные операционные системы (к коим относится и Windows XP) в совокупности с процессорами, поддерживающими 32-разрядную адресацию памяти (современные 64-разрядные процессоры при применении 32-разрядной ОС работают как 32-разрядные процессоры).

При 32-разрядной адресации памяти объем виртуальной адресуемой памяти составляет 232 = 4 Гбайт. При сегментно-страничной организации памяти адрес, как уже отмечалось, состоит из трех полей, которые определяют номер каталога страниц, номер страницы и смещение в пределах страницы. Для задания номера каталога и номера страницы используется по 10 бит, а для задания смещения — оставшиеся 12 бит. В этом случае поддерживается 210 =1 024 каталога страниц и 1024 страницы внутри каждого каталога, а общее количество страниц может составлять 220 = 1 048 576. Учитывая, что для задания смещения внутри страницы применяется 12 разрядов адреса, нетрудно посчитать, что размер одной страницы составляет 212 = 4096 байт = 4 Кбайт.

Рассмотрим более подробно отдельный элемент (запись) таблицы страниц (Page Table Element, PTE). Каждая запись таблицы страниц является 32-разрядной. Старшие пять разрядов определяют тип доступа к странице (нет доступа, только чтение, чтение и запись). Следующие 20 бит задают физический адрес страницы в памяти. Если учесть, что для задания смещения в пределах страниц используется 12 бит, то в совокупности с 20 битами, применяемыми для описания физического адреса страницы, получаем как раз 32-разрядную адресацию памяти. Следующие 4 бита в PTE определяют применяемый файл подкачки (один из 16 возможных), а последние 3 бита задают состояние страницы памяти. Первый из этих битов (T-бит, Transition) определяет, является ли страница переходной (T = 1) или нет (T = 0), второй бит (D-бит, Dirty) — была ли произведена в страницу запись (D = 1) или запись не проводилась (D = 0), последний бит (P-бит, Present) — находится ли страница в оперативной памяти (P = 1) или же в файле подкачки (P = 0). Информация о состоянии страницы необходима для того, чтобы принять решение о сохранении страницы в файле подкачки при ее вытеснении (принудительном освобождении занятой памяти). Действительно, если страница не изменялась в памяти после загрузки, то ее можно просто стереть, ведь в файле подкачки сохранилась ее копия.

Принцип работы менеджера памяти

Для управления виртуальной памятью в операционной системе Windows предусмотрен специальный менеджер Virtual Memory Manager (VMM). Он является составной частью ядра операционной системы и представляет собой отдельный процесс, постоянно находящийся в оперативной памяти. Основная задача VMM заключается в управлении страницами виртуальной памяти.

Каждому процессу (запущенному приложению) VMM выделяет часть физической памяти, которая называется рабочим набором (Working Set). Кроме того, VMM создает базу состояния страниц (page-frame database), которая организована как шесть списков страниц одного типа. Выделяют следующие типы страниц:

  • Valid — рабочая страница используется процессом. Такие страницы памяти реально существуют в физической памяти. Если процесс освобождает страницу памяти, то VMM убирает ее из списка Valid. Если процесс пытается обратиться к странице, которой нет в списке Valid, то генерируется ошибка (Page Fault) и VMM может отвести процессу новую страницу. Страницы типа Valid в таблице страниц описываются как присутствующие (P = 1);
  • Modified — модифицированная страница, то есть страница, содержимое которой было изменено. В таблице страниц данные страницы отмечаются как отсутствующие (P = 0) и переходные (T = 1);
  • Standby — резервная страница, содержимое которой не изменялось. В таблице страниц такие страницы отмечаются как отсутствующие (P = 0) и переходные (T = 1);
  • Free — свободная страница, на которую не ссылается ни один рабочий набор и которой нет ни в одной таблице страниц. В список Free помещаются страницы, которые освободились после окончания процесса. Свободные страницы могут применяться, однако прежде они подлежат процедуре обнуления (заполнения нулями). Процедурой обнуления страниц занимается специальная подпрограмма менеджера памяти Zero Page Thread;
  • Zeroed — пустая страница, которая является свободной и обнуленной. Такие страницы готовы к использованию любым процессом;
  • Bad — страница, которая вызывает аппаратные ошибки и не может применяться ни одним процессом.

Как уже отмечалось, если какой-нибудь процесс обращается к странице, которой нет в рабочем наборе (в списке Valid), то возникает ошибка обращения к странице. В этом случае задача VMM заключается в том, чтобы разрешить данную конфликтную ситуацию и выделить страницу свободной физической памяти для хранения данных, к которым обратился процесс. Существует несколько способов решения данной конфликтной ситуации. Во-первых, VMM может расширить рабочий набор процесса, добавив к нему необходимую страницу. Однако если в памяти нет места для выделения дополнительных страниц, то VMM замещает страницу, находящуюся в рабочем наборе, новой страницей. Понятно, что в идеале замещению должна подлежать та страница, к которой в будущем не будет обращений, или страница, которая не будет использоваться дольше других. Однако достоверного способа определить, какая именно страница отвечает перечисленным критериям, нет. Поэтому менеджер памяти применяет следующий хитроумный алгоритм. Он периодически просматривает список рабочих страниц (Valid) и помечает их как отсутствующие (P = 0). Однако данные страницы не удаляются из рабочего процесса — они остаются на месте и просто переводятся из категории Valid в категорию модифицированных (Modified) или резервных (Standby) страниц (естественно, никаких изменений в содержимом этих страниц не производится). Если измененная таким образом страница требуется какому-нибудь процессу, то происходит обращение к ней и возникает ошибка обращения к странице. Но поскольку в действительности страница находится в физической памяти и ее содержимое не подвергалось изменению, то менеджеру памяти достаточно просто перевести данную страницу обратно в категорию Valid, сделав ее доступной для процесса. Если же страница не используется в течение длительного времени процессами, то обращений к ней не происходит и она со временем переводится в категорию свободных (Free) страниц, а затем обнуляется и переводится в категорию пустых (Zeroed) страниц.

Таким образом, менеджер памяти автоматически забирает страницы из рабочих наборов неактивных процессов, то есть процессы, не проявляющие активности в течение длительного времени, автоматически освобождают всю физическую память.

На рис. 4 показаны переходы между различными категориями (списками) страниц.

Рис. 4. Переходы между различными категориями страниц памяти

Фокусы оптимизаторов памяти

После того как мы разобрались с основами организации памяти и принципами функционирования менеджера памяти в операционных системах семейства Windows, самое время рассмотреть, каким образом с помощью оптимизаторов памяти можно увеличить объем доступной (Available) физической памяти. Для операционной системы доступной памятью является сумма пустых (Zeroed), свободных (Free) и резервных (Standby) страниц.

Прежде всего отметим, что ни один оптимизатор памяти не может подменить собой менеджера памяти, который, как уже говорилось, является частью ядра операционной системы. Поэтому единственное, что может сделать оптимизатор памяти, — это вмешаться в работу менеджера памяти.

Итак, рассмотрим первую возможность, предоставляемую всеми оптимизаторами памяти, — увеличение доступной памяти. Достигается это следующим образом. Оптимизатор памяти, как и любая программа, является процессом, которому менеджер памяти выделяет свой рабочий набор. Оптимизаторы памяти ведут себя весьма агрессивно и требуют под свои нужды выделения все новых и новых страниц, то есть постоянно расширяют свой рабочий набор. Сделать это нетрудно — нужно лишь за короткое время реализовать многочисленные обращения к несуществующим страницам памяти, что вызывает ошибки обращения. В ответ на возникающие ошибки обращения менеджер памяти увеличивает рабочий набор оптимизатора сначала за счет доступной памяти, а когда лимит доступной памяти исчерпывается, расширение рабочего набора оптимизатора достигается за счет механизма замещения страниц, осуществляемого менеджером памяти. То есть рабочие наборы всех остальных процессов уменьшаются, а рабочий набор оптимизатора памяти увеличивается.

После того как рабочий набор, выделяемый оптимизатору памяти, достигает требуемого значения (это значение можно задавать в оптимизаторах памяти), оптимизатор памяти заканчивает свой процесс, высвобождая рабочий набор. В результате образуется большое количество (заданное в настройках оптимизатора) доступной памяти.

Описанный алгоритм увеличения доступной памяти, который используют все оптимизаторы памяти, имеет одно существенное негативное последствие. Дело в том, что, во-первых, такая «оптимизация» памяти приостанавливает работу всех остальных программ (особенно если оптимизация происходит в автоматическом режиме), а во-вторых, в процессе замещения страниц происходит вытеснение страниц, принадлежащих различным процессам, на жесткий диск ПК. После того как оптимизатор заканчивает свою работу, активным процессам, чьи рабочие наборы были вытеснены на диск, приходится повторно считывать данные с диска, что, конечно же, негативно сказывается на производительности ПК. Поэтому оптимизаторы памяти создают лишь иллюзию того, что они освобождают память, делая ее доступной. На самом деле, как только оптимизатор заканчивает свою деятельность, менеджер памяти возвращает все к исходному состоянию, но достигается это за счет снижения производительности системы.

Другой распространенный миф, связанный с оптимизаторами памяти, заключается в том, что эти утилиты якобы способны высвобождать память, занимаемую неактивными процессами, и предотвращать утечку памяти. Однако если вспомнить алгоритм работы менеджера памяти, то становится понятно, что эту задачу решает именно менеджер памяти, который автоматически высвобождает память неактивных процессов. Проблема утечки памяти, которая возникает по причине того, что некоторые процессы не могут корректно освободить память, также решается менеджером памяти, поскольку, как уже отмечалось, память всех неактивных процессов постоянно высвобождается. И даже если какой-то процесс остается незавершенным (хотя и неактивным), используемый им рабочий набор вытесняется в файл подкачки на жесткий диск.

Последний фокус оптимизаторов памяти связан с ее дефрагментацией. Дефрагментация памяти действительно присутствует, поскольку является побочным эффектом высвобождения большого (причем сплошного) объема памяти. Однако есть одно маленькое «но»! Все дело в том, что сплошной объем памяти является виртуальным, а информация о том, как именно расположены в физической памяти соответствующие страницы, остается недоступной оптимизатору памяти, поскольку соответствие между логическими и физическими адресами страниц определяется уже на аппаратном, а не на программном уровне. В итоге, несмотря на то, что виртуальная память дефрагментируется, физическая память остается нетронутой, а значит, и толку от такого рода дефрагментации нет никакого.

Практические примеры

После теоретического разоблачения оптимизаторов памяти перейдем к рассмотрению практических примеров. Мы выбрали несколько популярных оптимизаторов памяти, которые легко можно найти в Интернете. Думается, их будет вполне достаточно, чтобы убедиться в никчемности подобных устройств.

Для тестирования оптимизаторов памяти использовался ноутбук на базе мобильной технологии Intel Centrino, оснащенный процессором Intel Pentium M (Dothan) с тактовой частотой 1,6 ГГц и 512 Мбайт оперативной памяти DDR400.

Прежде чем приступать к рассмотрению того, как различные оптимизаторы влияют на производительность системы, проведем простой эксперимент, демонстрирующий действие менеджера памяти, входящего в состав операционной системы Windows XP Professional SP2.

Загрузим ноутбук и запустим Windows Task Manager, который позволяет контролировать объем доступной памяти (Avaliable). В нашем случае после загрузки операционной системы объем доступной памяти составляет 334 000 Кбайт (рис. 5).

Рис. 5. Объем доступной памяти после загрузки операционной системы

Далее последовательно загрузим несколько приложений: документ Word, Adobe Photoshop CS2 c фотографией размером 3 Мбайт, утилиту Paint и приложение Solid Works 2005 c загруженным проектом. После открытия всех указанных приложений, которые в первый момент воспринимаются операционной системой как активные, размер доступной памяти уменьшается до 47 300 Кбайт (рис. 6).

Рис. 6. Объем доступной памяти после загрузки приложений

Теперь сделаем приложения неактивными (для этого просто не будем производить каких-либо действий с компьютером) и понаблюдаем за изменением доступной памяти с помощью утилиты Windows Task Manager. Уже через 10 минут «бездействия» объем доступной памяти достигнет 311 500 Кбайт, то есть станет почти таким же, как и в случае загрузки операционной системы без указанных приложений. Данный пример доказывает, что менеджер памяти автоматически регулирует объем доступной памяти, изымая ее у неактивных процессов.

Для того чтобы продемонстрировать пагубное влияние оптимизаторов памяти, воспользуемся бенчмарком PCMark05. Все подтесты, входящие в этот тест, нам не потребуются, поскольку в данном случае нас не интересует производительность жесткого диска, графической подсистемы или латентность памяти. Мы выберем лишь подтесты, нуждающиеся в большом объеме оперативной памяти. Понятно, что эти подтесты должны быть многозадачными, поскольку в данном случае мы имеем несколько активных процессов, для каждого из которых в оперативной памяти создается свой рабочий набор. В бенчмарке PCMark05 многозадачными являются три подтеста: Multithreaded Test 1, Multithreaded Test 2 и Multithreaded Test 3.

Поскольку практически все оптимизаторы памяти позволяют задавать размер доступной памяти, по достижении которого автоматически начинается процедура высвобождения доступной памяти, мы установим данный барьер на уровне 220 000 Кбайт и попробуем запустить при этом тест PCmark05. Изменение размера доступной памяти контролируется с помощью утилиты Windows Task Manager.

В первом подтесте объем доступной памяти не ниже 210 000 Кбайт, во втором подтесте — не ниже 260 000 Кбайт, а в третьем — не ниже 214 000 Кбайт. Понятно, что для того, чтобы в ходе теста автоматически активировался оптимизатор памяти, необходимо выбрать барьер доступной памяти на уровне примерно 250 000 Кбайт. В этом случае в ходе выполнения первого и третьего подтестов будет активизироваться оптимизатор памяти.

dRAMatic v 8.1

Утилиту dRAMatic v 8.1 можно смело отнести к разряду классических оптимизаторов памяти. Она позволяет производить дефрагментацию оперативной памяти, хотя на самом деле под этим понимается просто высвобождение доступной памяти как в ручном, так и в автоматическом режиме. В последнем случае имеется возможность указать размер доступной памяти, по достижении которого оптимизатор автоматически начинает процесс ее высвобождения. Как выяснилось в ходе тестирования, утилита не слишком агрессивна и не представляет угрозы для активных процессов, которые активно утилизируют процессор. Так, отобрать страницы памяти у активных процессов в первом и втором подтестах утилита оказалась не в состоянии и ее автоматический запуск не реализовывался при достижении установленного барьера доступной памяти. В этом смысле данную утилиту можно было бы классифицировать как безвредную и бесполезную.

Clean RAM 1.21

Данная утилита отличается крайне простым интерфейсом и практически не имеет настроек. Автоматический режим работы утилиты не предусмотрен. Единственное, что можно сделать с ее помощью, — это в ручном режиме высвободить заданное количество доступной оперативной памяти. Кроме того, данная утилита показывает объем доступной памяти. Поэтому, если не нажимать на кнопку Clean RAM now (приступить к высвобождению памяти), утилиту Clean RAM 1.2 можно считать вполне безобидной.

FAST Defrag 2.3

Утилита FAST Defrag 2.3 поддерживает множество языков, в том числе и русский. Она работает как в ручном, так и в автоматическом режиме. В ручном режиме можно указать объем высвобождаемой памяти. Автоматический режим работы утилиты предусматривает несколько возможных настроек. Так, можно задать автоматическую очистку памяти при достижении заданного значения загрузки процессора (от 1 до 99%), при достижении заданного значения загрузки памяти (от 1 до 100%) и при достижении заданного значение оставшейся свободной памяти (от 1 до 25%). Кроме того, имеется возможность задать автоматическую очистку памяти при старте утилиты.

При тестировании утилиты FAST Defrag 2.3 с помощью бенчмарка PCMark05 выяснилось, что достичь объема оставшейся свободной памяти в 25% не удается, поэтому для автоматического запуска утилиты мы применяли критерий загрузки процессора, установив порог, равный 99%. Данный уровень загрузки процессора достигается во всех трех подтестах бенчмарка PCMark05, поэтому формально автоматическая очистка памяти должна была бы запускаться в каждом из подтестов. Но выяснилось, что утилита не такая уж и агрессивная и что при загрузке процессора в 100% она не может начать оптимизацию памяти. Поэтому действие этой утилиты никак не отражалось на результатах теста.

В целом же можно констатировать, что FAST Defrag 2.3 — это еще один совершенно бесполезный (правда, и безвредный) оптимизатор памяти.

FreeRAM XP Pro 1.52

Данную утилиту можно отнести к разряду продвинутых и весьма вредоносных оптимизаторов памяти.

Как и большинство оптимизаторов памяти, FreeRAM XP Pro 1.52 может запускаться как в ручном, так и в автоматическом режиме. Отличительной его особенностью является большое количество всевозможных настроек, создающих иллюзию полезности решения.

В ручном режиме можно задать размер доступной памяти, которая должна быть высвобождена. Естественно, это не означает, что при оптимизации указанный размер будет достигнут.

Для запуска утилиты в автоматическом режиме предусмотрена масса настроек, которые определяют критерии запуска. Так, можно настроить запуск оптимизатора через определенные временные интервалы или при достижении определенного значения доступной памяти. Кроме того, можно настраивать условия запуска в зависимости от загрузки процессора, временной интервал ожидания перед запуском оптимизатора и многое другое.

Как выяснилось в ходе тестирования, утилита ведет себя довольно агрессивно и способна начать оптимизацию памяти даже при 100% загрузке процессора. Естественно, что в этом случае производительность в тесте падает. Во-первых, оптимизатор памяти постоянно запускается, утилизируя процессор, а во-вторых, из-за высвобождения доступной памяти происходит постоянное вытеснение рабочих наборов активных процессов на жесткий диск и их последующая подкачка. Собственно, именно это и можно наблюдать по результатам теста, которые значительно ухудшаются.

Memory Optimizer 2002a

Оптимизатор Memory Optimizer 2002a имеет простой интерфейс и как и большинство оптимизаторов памяти, допускает как ручную, так и автоматическую оптимизацию памяти. Возможности настройки оптимизатора вполне типичны. При настройке автоматического режима необходимо указать критерии запуска утилиты.

В ходе тестирования выяснилось, что утилита ведет себя весьма агрессивно и способна высвобождать память даже при 100% загрузке процессора. Естественно, такая агрессия в отношении активных процессов отрицательно сказывается на результатах теста.

MemTurbo 2

MemTurbo 2 — еще один оптимизатор памяти, который можно отнести к разряду безвредных. Оптимизатор обладает красивым графическим интерфейсом, а объем доступной памяти отображает в графическом виде. Данная утилита допускает работу оптимизатора в ручном и автоматическом режимах и предлагает большое количество настроек. В частности, предусмотрено множество настроек для автоматического запуска оптимизатора.

Как выяснилось в ходе тестирования, настройка утилиты на автоматический запуск по критерию достижения заданного размера оставшейся доступной памяти не сказывается на результатах теста. Дело в том, что, несмотря на выполнение критерия автозапуска, при 100% загрузке процессора оптимизация памяти не начинается. Поэтому данная утилита не оказывала влияния на действие активных процессов в ходе тестирования.

В целом можно отметить, что данная утилита не является агрессивной и в этом смысле безобидна, но и бесполезна (впрочем, как и все оптимизаторы памяти).

RAM Idle Professional 3.4

Утилиту RAM Idle Professional 3.4 можно отнести к разряду твикеров операционной системы, но, поскольку одно из центральных мест в ней занимает оптимизатор памяти, мы решили рассмотреть ее в нашем обзоре.

По возможностям настройки оптимизатор RAM Idle Professional 3.4 отличается от других тем, что в нем не предусмотрено ручного режима оптимизации. При настройке автоматического режима допускается указание критического размера доступной памяти. Кроме того, можно настроить автоматическую оптимизацию после старта программы через заданный интервал времени, а также автоматический запуск оптимизации через заданные временные промежутки. В последнем случае можно указать, какой объем памяти требуется освободить в процессе оптимизации.

Тестирование оптимизатора RAM Idle Professional 3.4 показало, что данная программа ведет себя довольно агрессивно. Оптимизация памяти происходит даже при 100% нагрузке на процессор, что, естественно, отрицательно сказывается на результатах теста.

Выводы

Рассмотрение оптимизаторов памяти можно было бы продолжать и далее. Однако, думается, в этом нет необходимости. Все оптимизаторы построены по одному и тому же принципу и отличаются лишь интерфейсом, настройками и своей агрессивностью. Менее агрессивные оптимизаторы не приносят особого вреда (как, впрочем, и пользы), а использование агрессивных оптимизаторов может привести к падению производительности системы. Нужны ли утилиты, создающие иллюзию того, что за счет их применения увеличивается производительность ПК, — решать вам.

КомпьютерПресс 6’2006

Обзор методов управления памятью

Обзор методов управления памятью

Обо всех деталях отображения виртуальных адресов на физические адреса (virtual to physical memory mapping), механизмах страничной подкачки (page swapping) и замещения страниц по запросу (demand paging) и прочих моментах заботится ОС. Эти вопросы подробно обсуждаются в документации по ОС, а также в книге Соломона (Solomon) и Руссиновича (Russinovich) Inside Windows2000. Краткое изложение наиболее существенных сведений приводится ниже:

• Система может располагать сравнительно небольшим объемом физической памяти; на практике для всех систем, кроме Windows XP, необходимый минимум составляет 128 Мбайт, однако в типичных случаях доступные объемы физической памяти оказываются намного большими.[21]

• Каждый отдельный процесс — а таких процессов, как пользовательских, так и системных, может выполняться одновременно несколько — имеет собственное виртуальное адресное пространство, объем которого может значительно превосходить объем доступного физического адресного пространства. Например, емкость виртуального адресного пространства объемом 1 Гбайт, относящегося к одному процессу, в восемь раз превышает емкость физической памяти объемом 128 Мбайт, и таких процессов может быть множество.

• ОС преобразует виртуальные адреса в физические адреса.

• Для большинства виртуальных страниц в физической памяти места не хватит, поэтому ОС имеет возможность реагировать на страничные ошибки (page faults), возникающие при попытках обращения к страницам, которые отсутствуют в памяти, и загружать данные с жесткого диска — из системного файла подкачки (swap file) или из обычного файла. Будучи прозрачными для программиста, страничные ошибки отрицательно влияют на производительность, поэтому программы должны проектироваться таким образом, чтобы вероятность возникновения подобных ошибок была сведена к минимуму. Более подробное освещение этой темы, рассмотрение которой выходит за рамки данной книги, вы найдете в справочной документации по ОС.

На рис. 5.1 проиллюстрировано расположение уровней API управления памятью Windows поверх диспетчера виртуальной памяти (Virtual Memory Manager, VMM). API виртуальной памяти Windows (VirtualAlloc, VirtualFree, Virtual-Lock, VirtualUnlock и так далее) работает с целыми страницами. API кучи Windows управляет блоками памяти, размер которых определяется пользователем.

Мы не будем останавливаться на топологии адресного пространства виртуальной памяти, поскольку она не имеет непосредственного отношения к API, различна в Windows 9x и Windows NT и в будущем может измениться. Соответствующая информация содержится в документации Microsoft.

Тем не менее, многим программистам хотелось бы знать больше о своей среде разработки. Начните исследование структуры памяти в вашей системе с вызова следующей функции:

VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo) 

Параметром этой функции служит адрес структуры PSYSTEM_INFO, в которой содержится информация относительно размера системной страницы, а также адресах физической памяти, доступных для приложений.

Читайте также

9.2.1. Обзор управления заданиями

9.2.1. Обзор управления заданиями
Управление заданиями является сложной темой, той, в которую мы решили не погружаться в данной книге. Однако, здесь приведен краткий концептуальной обзор.Устройство терминала (физическое или другое) с работающим на нем пользователем

Архитектура системы управления памятью в Win32 и Win64

Архитектура системы управления памятью в Win32 и Win64
Win32 (в данном случае различия между Win32 и Win64 становятся существенными) — это API 32-разрядных ОС семейства Windows. «32-разрядность» проявляет себя при адресации памяти тем, что указатели (LPSTR, LPDWORD и так далее) являются 4-байтовыми

Обзор методов асинхронного ввода/вывода Windows

Обзор методов асинхронного ввода/вывода Windows
В Windows выполнение асинхронного ввода/вывода обеспечивается в соответствии с тремя методиками.• Многопоточный ввод/вывод (Multihreaded I/O). Каждый из потоков внутри процесса или набора процессов выполняет обычный синхронный

3.7. Обзор возможностей современных систем управления политиками безопасности

3.7. Обзор возможностей современных систем управления политиками безопасности
Как правило, современные системы управления политиками безопасности используют лицензированные библиотеки политик безопасности, разработанные другими компаниями. Так, например, продукт

Принципы управления памятью

Принципы управления памятью
Одной из основных функций операционной системы является эффективное управление памятью. Оперативная память, или основная память, или память с произвольным доступом (Random Access Memory, RAM) является достаточно дорогостоящим ресурсом. Время доступа к

Управление памятью процесса

Управление памятью процесса
Можно сказать, что каждый процесс в операционной системе UNIX выполняется на собственной виртуальной вычислительной машине, где все ресурсы принадлежат исключительно данному процессу. Подсистема управления памятью обеспечивает такую

2.2.1 Обзор особенностей подсистемы управления файлами

2.2.1 Обзор особенностей подсистемы управления файлами
Внутреннее представление файла описывается в индексе, который содержит описание размещения информации файла на диске и другую информацию, такую как владелец файла, права доступа к файлу и время доступа. Термин

ГЛАВА 9. АЛГОРИТМЫ УПРАВЛЕНИЯ ПАМЯТЬЮ

ГЛАВА 9. АЛГОРИТМЫ УПРАВЛЕНИЯ ПАМЯТЬЮ
Алгоритм планирования использования процессорного времени, рассмотренный в предыдущей главе, в сильной степени зависит от выбранной стратегии управления памятью. Процесс может выполняться, если он хотя бы частично присутствует в

18.1.3. Управление памятью

18.1.3. Управление памятью
Управление памятью осуществляется с помощью параметра mem: mem=Определяет объем памяти, установленной в компьютере.Например: mem=16384K или mem=16M.Иногда нужно указать объем ОЗУ, отличный от того, который имеется на самом деле. Например, у вас чипсет Intel 810 с

23.2.2. Функции для работы с памятью

23.2.2. Функции для работы с памятью
Функции для работы с памятью библиотеки Glib выполняют те же действия, что и соответствующие им функции языка С. Вот их прототипы:gpointer g_malloc(gulong size);gpointer g_realloc(gpointer mem, gulong size);void g_free(gpointer

Шаг 18 — Управление памятью.

Шаг 18 — Управление памятью.
Больше нет возможности обходить эту тему. Это слишком важно. Долго не хотел браться за нее, но она сама взялась за меня.В управлении памятью одна из самых больших проблем (для меня) состоит в том,что у авторов книг по C++ в этом месте случается как бы

Шаг 19 — Управление памятью. Продолжение 1.

Шаг 19 — Управление памятью. Продолжение 1.

Бог: «Я стер всякую жизнь. Впочем, я ничего не уничтожил. Я просто воссоединил в Себе частицы Себя. У меня на планете было множество типов с безумными глазами, которые болтали насчет слияния со Мной. Вот они и слились.»
Кармоди: «Им это

Примитивы управления памятью (Memory Handling Primitives)

Примитивы управления памятью (Memory Handling Primitives)
Чтобы получать типичный указатель на неинициализированный буфер памяти данного размера, определена следующая функция:template ‹class T›inline T* allocate(ptrdiff_t n, Т*); // n ›= 0Размер (в байтах) распределённого буфера — не меньше n*sizeof(T).Для

Лекция 9. Управление памятью

Лекция 9. Управление памятью

Честно говоря, было бы неплохо забыть про память. Программы создавали бы объекты по мере надобности. Неиспользованные объекты исчезали бы в небытие, а необходимые медленно передвигались бы вверх. Этот процесс подобен движению по служебной

Проблема управления памятью в ОО-модели

Проблема управления памятью в ОО-модели
Подводя итог предшествующего анализа, определим оригиналы и соответственно достижимые объекты:Определение: начальные, достижимые и недостижимые объектыВ каждый момент времени выполнения системы множество оригиналов

Управление памятью в Windows

Прежде чем перейти к рассмотрению формата PE, необходимо поговорить об особенностях управления памятью в Windows, так как без знания этих особенностей невозможно понять некоторые существенные детали формата.

Управление памятью в Windows NT/2k/XP/2k3 осуществляет менеджер виртуальной памяти (virtual-memory manager). Он использует страничную схему управления памятью, при которой вся физическая память делится на одинаковые отрезки размером в 4096 байт, называемые физическими страницами. Если физических страниц не хватает для работы системы, редко используемые страницы могут вытесняться на жесткий диск, в один или несколько файлов подкачки (pagefiles). Вытесненные страницы затем могут быть загружены обратно в память, если возникнет необходимость. Таким образом, программы могут использовать значительно большее количество памяти, чем реально присутствует в системе.

Виртуальное адресное пространство процесса

Каждый процесс в Windows запускается в своем виртуальном адресном пространстве размером в 4 Гб. При этом первые 2 Гб адресного пространства могут непосредственно использоваться процессом, а остальные 2 Гб резервируются операционной системой для своих нужд (рис. 2.1).

Виртуальное адресное пространство процесса

Рис.
2.1.
Виртуальное адресное пространство процесса

Виртуальное адресное пространство также делится на виртуальные страницы размером в 4096 байт. При этом процессу выделяется только то количество виртуальных страниц, которое ему реально нужно. Поэтому тот факт, что процесс может адресовать 4 Гб виртуального адресного пространства, еще не означает, что каждому процессу выделяется по 4 Гб оперативной памяти. Как правило, процесс использует только малую часть своего адресного пространства, хотя стремительное удешевление модулей памяти способно в самое ближайшее время существенно изменить картину и вызвать повсеместно переход к 64-разрядным архитектурам.

Виртуальные страницы могут отображаться операционной системой в страницы физической памяти, могут храниться в файле подкачки, а также могут быть вообще недоступны процессу. Обращение к недоступной виртуальной странице вызывает аварийное завершение процесса с сообщением «Access violation«.

Адресное пространство процесса называется виртуальным, потому что процесс для работы с памятью использует не реальные адреса физической памяти, а так называемые виртуальные адреса. При обращении по некоторому виртуальному адресу происходит перевод этого виртуального адреса в физический адрес. Перевод виртуальных адресов в физические адреса реализован на аппаратном уровне в процессоре и поэтому осуществляется достаточно быстро.

Перевод виртуального адреса в физический адрес

Рис.
2.2.
Перевод виртуального адреса в физический адрес

Рассмотрим на примере, как осуществляется перевод некоторого виртуального адреса vx в физический адрес px (рис 2.2). Сначала вычисляется номер vnum виртуальной страницы, соответствующий виртуальному адресу vx, а также смещение delta виртуального адреса относительно начала этой виртуальной страницы:

vnum := vx div 4096;
delta := vx mod 4096;

Далее возможны три варианта развития событий:

  1. Виртуальная страница vnum недоступна. В этом случае перевод виртуального адреса vx в физический адрес невозможен, и процесс завершается с сообщением «Access Violation«;
  2. Виртуальная страница находится в файле страничной подкачки, и ее надо сначала загрузить в память. Тогда пусть pnum будет номером физической страницы, в которую мы загружаем нашу виртуальную страницу;
  3. Виртуальная страница уже находится в памяти, и ей соответствует некоторая физическая страница. В этом случае pnum — номер этой физической страницы.

После чего адрес px вычисляется следующим образом:

Такая организация памяти процесса обладает следующими свойствами:

  • Процессы изолированы друг от друга. Один процесс не может обратиться к памяти другого процесса.
  • Передача виртуальных адресов между процессами совершенно бессмысленна. Один и тот же виртуальный адрес в адресных пространствах разных процессов соответствует разным физическим адресам.
  • Процессы используют преимущества плоской адресации памяти. Виртуальный адрес представляет собой 32-разрядное целое значение, что делает возможной легкую реализацию адресной арифметики.
Отображаемые в память файлы

Отображаемые в память файлы (memory-mapped files) — это мощная возможность операционной системы. Она позволяет приложениям осуществлять доступ к файлам на диске тем же самым способом, каким осуществляется доступ к динамической памяти, то есть через указатели. Смысл отображения файла в память заключается в том, что содержимое файла (или часть содержимого) отображается в некоторый диапазон виртуального адресного пространства процесса, после чего обращение по какому-либо адресу из этого диапазона означает обращение к файлу на диске. Естественно, не каждое обращение к отображенному в память файлу вызывает операцию чтения/записи. Менеджер виртуальной памяти кэширует обращения к диску и тем самым обеспечивает высокую эффективность работы с отображенными файлами.

Самый простой
способ узнать, сколько оперативной
памяти используется в данный момент
времени — открыть Диспетчер задач (Task
Manager), нажав [Ctrl]+[Shift]+[Esc], и перейти на
вкладку «Быстродействие» (Performance)
(рис.3.8). Подробное описание информации
вкладки «Быстродействие» для Windows
XP
представлено в табл. 3.1.

Рис.
3.8а. Диспетчер задач Windows
XP

Рис.
3.8б. Диспетчер задач Windows
7

Таблица 3.1.
Расшифровка данных Диспетчера задач

Категория

Значение

Смысл

Всего
(Totals)

Дескрипторов
(Handles)

Уникальные
идентификаторы, позволяющие программам
обращаться к системным ресурсам, таким
как файлы, ключи реестра, шрифты и
растровые изображения. Теоретически
это значение может использоваться
для выявления программ, не освобождающих
системные ресурсы после завершения
работы. На практике оно оказывается
полезным в основном для разработчиков,
использующих специализированные
средства отладки для выявления утечек
памяти в приложениях

Потоков
(Threads)

Поток — объект
внутри процесса, выполняющий инструкции
программы. Многопоточные программы
могут делать несколько операций
одновременно. Как и предыдущее, это
значение полезно в основном для
разработчиков программ в процессе
тестирования приложений

Процессов
(Processes)

Общее
количество процессов (программ,
подсистем и служб), инициированных
всеми пользователями данного компьютера

Выделение памяти

(Commit
Charge)

Всего
(Total)

Общее
количество физической и виртуальной
памяти, занимаемой операционной
системой и всеми программами в настоящий
момент. Это значение также отображается
в нижнем правом углу окна Диспетчера
задач. Выделение памяти растет по мере
открытия программ и файлов данных и
должно уменьшаться при их закрытии

Предел
(Limit)

Общее
количество физической и виртуальной
памяти, доступной операционной системе
и всем приложениям, которые о тоже
отображается в нижнем правом углу
Диспетчера задач. Чтобы увеличить
предельное значение, добавьте в
компьютер оперативной памяти и/или
увеличьте размер файла подкачки

Пик
(Peak)

Максимальное
общее количество памяти, использовавшееся
на протяжении текущего сеанса (в
килобайтах). Если это значение часто
оказывается близким или равным Пределу,
в систему нужно нарастить память

Физическая
память (Physical memory)

Всего
(Total)

Полное количество
физической памяти данного компьютера
(в килобайтах). Поделите на 1024, чтобы
перевести это значение в мегабайты

Доступно
(Available)

Общий объем
физической памяти (в килобайтах),
который будет выделен выполняемым
программам прежде, чем начнется обмен
данными с файлом подкачки. Windows всегда
старается зарезервировать некоторое
количество памяти для новых приложений,
даже если оно превышает количество
установленной физической памяти

Системный
кэш (System Cache)

Общее
количество физической памяти (в
килобайтах), используемое для хранения
часто вызываемых программ и данных.
Windows пытается отвести под системный
кэш как можно больше памяти, но при
необходимости будет уменьшать объем
кэша для предоставления программам
и функциям операционной системы
свободной памяти

Память
ядра (Kernel Memory)

Всего
(Total)

Полный
объем оперативной памяти (в килобайтах),
занимаемый основными компонентами
операционной системы (включая драйверы)

Выгружаемая
(Paged)

Объем
памяти (в килобайтах), используемой
основными компонентами Windows и
отображенной на страницы в виртуальной
памяти

Невыгружаемая
(Nonpaged)

Объем
кода операционной системы и драйверов
(в килобайтах), который должен выполняться
в физической памяти и не может быть
перенесен в виртуальную

Вкладка
«Быстродействие» для Windows
7 имеет значимые нововведения по сравнению
с соответствующей вкладкой Диспетчером
задач Windows XP.

Число в графе
«Всего» (Total) раздела «Физическая память»
(Physical Memory) указывает на общий объем
оперативной памяти для данной системы.
В графе «Кэшировано» (Cached) указано
количество физической памяти, которая
недавно использовалась системными
ресурсами. Она остается в кэше на случай,
если снова понадобится системе, но
доступна для других процессов. В новой
графе «Доступно» (Available) указывается
количество неиспользуемой в данный
момент физической памяти, а в графе
«Свободно» (Free) — количество памяти,
которая используется кэшем, но не
содержит полезной информации.

В разделе «Память
ядра» (Kernel Memory) содержатся две графы —
«Выгружаемая» (Paged) и «Невыгружаемая»
(Nonpaged). В сумме они указывают, сколько
памяти использует ядро. Выгружаемая —
это виртуальная память, а невыгружаемая
— физическая.

В разделе «Система»
(System) появились графы «Дескрипторов»
(Handles) и «Потоков» (Threads), связанные с
составными компонентами процессов. В
графе «Дескрипторов» указывается
количество идентификаторов объектов
(дескрипторов), которые используются
запущенными в данный момент процессами.
В графе «Потоков» указано число
подпроцессов, запущенных в рамках более
крупных процессов. Цифра в графе
«Процессов» (Processes), естественно, указывает
на общее количество запущенных процессов,
которые можно увидеть на вкладке
«Процессы».

В графе «Время
работы» (Up Time) указано, сколько времени
прошло с последнего запуска компьютера.
В графе «Выделено» (Commit) содержится
информация о файле подкачки. Первая
цифра указывает на общий объем используемой
в данный момент физической и виртуальной
памяти, а вторая — на общий объем памяти
для данного компьютера в принципе.

Еще более подробную
информацию можно получить, нажав кнопку
«Монитор ресурсов» и выбрав вкладку
«Память» (рис. 3.9).

Рис. 3.9. Вкладка
«Память» окна монитора ресурсов Windows
7

На вкладке «Память»
есть таблица «Процессы», в которой
перечислены все запущенные процессы,
а сведения об используемой памяти для
каждого процесса разбиты на несколько
категорий (рис.3.10).

Рис. 3.10. Таблица
«Процессы»

В колонке «Образ»
указывается имя исполняемого файла
процесса. Процессы, запущенные
приложениями, узнать очень легко —
например, процесс «Winword.exe»
со всей очевидностью принадлежит
текстовому редактору Word.
Процессы с именем «svchost.exe» представляют
различные службы операционной системы.
Название службы указывается в скобках
рядом с именем процесса.

В колонке «ИД
процесса
»
указывается номер процесса — уникальное
сочетание цифр, позволяющее идентифицировать
запущенный процесс.

В столбце «Завершено»
указывается объем виртуальной памяти
в килобайтах, зарезервированный системой
для данного процесса. Сюда входит и
используемая физическая память, и
сохраненные в файле подкачки страницы.

В графе «Рабочий
набор
»
указывается объем физической памяти в
килобайтах, используемой процессом в
данный момент времени. Рабочий набор
складывается из общей и частной памяти.

В колонке «Общий»
указан объем физической памяти в
килобайтах, которую данный процесс
использует совместно с другими.
Использование одного сегмента памяти
или страницы подкачки для родственных
процессов позволяет сэкономить место
в памяти. При этом физически сохраняется
только одна копия страницы, которая
затем сопоставляется с виртуальным
адресным пространством других процессов,
которые к ней обращаются. Например, все
процессы, инициированные системными
библиотеками DLL — Ntdll, Kernel32, Gdi32 и User32 —
используют общую память.

В столбце «Частный»
указывается объем физической памяти в
килобайтах, используемой исключительно
данным процессом. Именно это значение
позволяет определить, сколько памяти
нужно тому или иному приложению для
работы.

В графе «Ошибок
отсутствия страницы в памяти/сек.
»
указано среднее за последнюю минуту
количество ошибок отсутствия страницы
в памяти в секунду. Если процесс пытается
использовать больше физической памяти,
чем доступно в данный момент времени,
система записывает часть данных из
памяти на диск — в файл подкачки.
Последующее обращение к данным,
сохраненным на диск, и называется ошибкой
отсутствия страницы в памяти.

При запуске
приложений и работе с файлами диспетчер
памяти отслеживает объем рабочего
набора для каждого процесса и фиксирует
запросы на дополнительные ресурсы
памяти. По мере увеличения рабочего
набора процесса, диспетчер соотносит
эти запросы с потребностями ядра и
других процессов. Если доступного
адресного пространства недостаточно,
диспетчер уменьшает объем рабочего
набора, сохраняя данные из памяти на
диск.

В дальнейшем при
чтении этих данных с диска возникает
ошибка отсутствия страницы в памяти.
Это вполне нормально, но если ошибки
происходят одновременно для разных
процессов, системе требуется дополнительное
время для чтения данных с диска. Слишком
частые ошибки отсутствия страницы в
памяти, соответственно, снижают
быстродействие системы. Это проявляется
в неожиданном замедлении работы всех
приложений, которое затем также неожиданно
прекращается. Замедление связано с
активным перераспределением данных
между физической памятью и подкачкой.

Отсюда следует
вывод: если ошибки отсутствия страницы
в памяти для того или иного процесса
происходят слишком часто и притом
регулярно, компьютеру не хватает
физической памяти.

Чтобы было удобнее
наблюдать за процессами, вызывающими
частые ошибки отсутствия страницы в
памяти, можно отметить их флажками. При
этом выбранные процессы переместятся
наверх списка, а в графике ошибок
отсутствия страницы в памяти будут
представлены оранжевой кривой.

Стоит учитывать,
что распределение памяти зависит от
целого ряда других факторов, и мониторинг
ошибок отсутствия страницы в памяти —
не лучший и не единственный способ
выявления проблем. Тем не менее, он может
послужить неплохой отправной точкой
для наблюдения.

В
таблице «Процессы» приводятся детальные
сведения о распределении памяти между
отдельными процессами, а таблица
«Физическая память» дает общую картину
использования RAM. Ее ключевой компонент
— уникальная гистограмма, показанная
на рис. 3.11.


Рисунок
3.11. Гистограмма в таблице «Физическая
память» позволяет составить общее
представление о распределении памяти
в Windows 7

Каждая секция
гистограммы обозначена собственным
цветом и представляет определенную
группу страниц памяти. По мере использования
системы, диспетчер памяти в фоновом
режиме перемещает данные между этими
группами, поддерживая тонкий баланс
между физической и виртуальной памятью
для обеспечения эффективной работы
всех приложений. Рассмотрим гистограмму
поподробнее.

Слева расположена
секция «Зарезервированное
оборудование
»,
обозначенная серым цветом: это память,
выделенная на нужды подключенного
оборудования, которую оно использует
для взаимодействия с операционной
системой. Зарезервированная для
оборудования память заблокирована и
недоступна диспетчеру памяти. Обычно
объем памяти, выделенной оборудованию,
составляет от 10 до 70 Мбайт, однако этот
показатель зависит от конкретной
конфигурации системы и в некоторых
случаях может достигать нескольких
сотен мегабайт.

К компонентам,
влияющим на объем зарезервированной
памяти, относятся:

• BIOS;

• компоненты
материнской платы — например,
усовершенствованный программируемый
контроллер прерываний ввода/вывода
(APIC);

• звуковые карты
и другие устройства, осуществляющие
ввод/вывод с отображением на память;

• шина PCI Express
(PCIe);

• видеокарты;

• различные наборы
микросхем;

• флеш-накопители.

Секция «Используется»,
обозначенная зеленым цветом, представляет
количество памяти, используемой системой,
драйверами и запущенными процессами.
Количество используемой памяти
рассчитывается, как значение «Всего»
за вычетом суммы показателей «Изменено»,
«Ожидание»
и «Свободно».
В свою очередь, значение «Всего»
— это показатель «Установлено»
за вычетом показателя «Зарезервированное
оборудование
».

Оранжевым цветом
выделена секция «Изменено»,
в которой представлена измененная, но
не задействованная память. Фактически
она не используется, но может быть в
любой момент задействована, если снова
понадобится. Если память не используется
достаточно давно, данные переносятся
в файл подкачки, а память переходит в
категорию «Ожидание».

Секция «Ожидание»,
обозначенная синим цветом, представляет
страницы памяти, удаленные из рабочих
наборов, но по-прежнему с ними связанные.
Другими словами, категория «Ожидание»
— это фактически кэш. Страницам памяти
в этой категории присваивается приоритет
от 0 до 7 (максимум). Страницы, связанные
с высокоприоритетными процессами,
получают максимальный приоритет.
Например, совместно используемые
процессы обладают высоким приоритетом,
поэтому связанным с ними страницам
присваивается наивысший приоритет в
категории «Ожидание».

Если процессу
требуются данные с ожидающей страницы,
диспетчер памяти сразу же возвращает
эту страницу в рабочий набор. Тем не
менее, все страницы в категории «Ожидание»
доступны для записи данных от других
процессов. Когда процессу требуется
дополнительная память, а свободной
памяти недостаточно, диспетчер памяти
выбирает ожидающую страницу с наименьшим
приоритетом, инициализирует ее и выделяет
запросившему процессу.

В категории
«Свободно»,
обозначенной голубым цветом, представлены
страницы памяти, еще не выделенные ни
одному процессу или освободившиеся
после завершения процесса. В этой секции
отображается как еще не задействованная,
так и уже освобожденная память, но на
самом деле, еще не задействованная
память относится к другой категории —
«Нулевые
страницы
»,
которая так называется, потому что эти
страницы инициализированы нулевым
значением и готовы для использования.

С системой управления
памятью в Windows 7 связано одно весьма
распространенное заблуждение. Как видно
из рис. 3.11, секция свободной памяти —
одна из самых маленьких в гистограмме.
Тем не менее, ошибочно на этом основании
полагать, будто Windows 7 потребляет чересчур
много памяти и что система не может
нормально работать, если свободной
памяти так мало. На самом деле, все совсем
наоборот.

В контексте
принятого в Windows 7 подхода к управлению
памятью, свободная память бесполезна.
Чем больше памяти задействовано, тем
лучше!!!

Заполняя память
до максимума и постоянно перемещая
страницы из одной категории в другую с
использованием системы приоритетов,
Windows 7 повышает эффективность работы и
предотвращает попадание данных в файл
подкачки, не давая ошибкам отсутствия
страницы в памяти замедлить быстродействие.

Порядок выполнения
работы

1. Перезагрузите
компьютер и сразу же после запуска
откройте Монитор ресурсов Windows 7.

2. Перейдите на
вкладку «Память» и обратите внимание
на соотношение секций в гистограмме
физической памяти.

3. Начните запускать
приложения. По мере запуска следите за
изменением гистограммы. Запустив как
можно больше приложений, начните
закрывать их по одному и наблюдайте,
как изменяется соотношение секций в
гистограмме физической памяти.

РЕКОМЕНДУЕМАЯ
ЛИТЕРАТУРА

  1. Гордеев
    А.В. Операционные системы: Учебник для
    вузов. 2-е изд. – СПб.: Питер, 2009. – 416 с.

  2. Х.М.
    Дейтл, П.Дж. Дейтл, Д.Р. Чофнес Операционные
    системы. Основы и принципы: Третье
    издание. Пер. с англ. –М.: ООО «Бином-Пресс»,
    2006 г. – 1024 с.

  3. Шоу
    А. Логическое проектирование операционных
    систем: Пер. с англ. – М.: Мир, 1981. – 360 с.

  4. Рихтер
    Дж. Windows для профессионалов: создание
    эффективных Win32 приложений с учетом
    специфики 64-разрядной версии Windows/Пер,
    англ — 4-е изд. — СПб; Питер; М.:
    Издательско-торговый дом «Русская
    Редакция», 2001. — 752 с.; ил.

  5. Иртегов
    Д.В. Введение в операционные системы.
    – 2-е изд., перераб. и доп. – СПБ;
    БХВ-Петербург, 2008. – 1040 с., ил. — (Учебное
    пособие)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

The memory management in the operating system is to control or maintain the main memory and transfer processes from the primary memory to disk during execution. Memory management keeps track of all memory locations, whether the process uses them or not. Determines how much memory should be allocated to each process. Specifies how much memory each process should be given. It decides which processes will be remembered and when. It tracks when memory is released or when it is shared and changes the status accordingly.

Windows Memory Management

Microsoft Windows has its own virtual address space for each 32-bit process, allowing up to 4 gigabytes of memory to be viewed. Each process has 8-terabyte address space on 64-bit Windows. All threads have access to the visible address space of the process. Threads, on the other hand, do not have access to the memory of another process, which protects one process from being damaged by another.

Architecture for 32-bit Windows: The automatic configuration of the 32-bit Windows Operating System (OS) allocates 4 GB (232) of accessible memory space to the kernel and user programs equally. With 4 GB physical memory available, the kernel will receive 2 GB and the app memory will receive 2 GB. Kernel-mode address space is shared by all processes, but application mode access space is provided for each user process.

Architecture for 64-bit Windows: The automatic configuration of the 64-bit Windows Operating System (OS) allocates up to 16 TB (254) of accessible memory space to the kernel and user programs equally. As 16 TB real memory is available, the kernel will have 8 TB of virtual address (VA) space and user application memory will have 8 TB of VA space. Visible address space in the kernel is allocated for all processes. Each 64-bit functionality gets its place, but each 32-bit system works on a 2 GB (Windows) virtual machine.

Virtual Address Space

The process’ visible address space is the range of memory addresses that you can use. The address area of ​​each process is private, and can only be accessed through other processes if it is shared.

A virtual address does not reflect the actual location of an object in memory; instead, the system stores a table for each process, which is an internal data structure that converts visible addresses into local addresses. The program converts the virtual address into a local address every time the chain refers to it.

The virtual address area of Windows is divided into two parts: one for process use and the other for system usage.

Virtual Memory Functions

A process can alter or determine the state of pages in its virtual address space using virtual memory functions.

The width of the visible address space is reserved for the process. Although saving address space does not provide material storage, it prevents scope from using other sharing processes. It does not affect other active address spaces for other processes. Page storage reduces unnecessary use of virtual storage while allowing the process of setting aside part of its address space for the flexible data structure. As required, the procedure can provide a physical repository for this area.

Provide a set of cached pages in the address of the process so that only a shared process can access real storage (either RAM or disk).

For the most dedicated pages, specify read/write, read-only, or no access. This differs from the general distribution procedures, which often provide read/write access to the pages.

Release a set of saved pages, making the visible address set accessible for the following call process sharing actions.

We can withdraw a group of committed pages, freeing up portable storage that can be assigned to any process in the future.

To prevent the program from changing pages in the file, lock one or more memory pages bound to the virtual memory (RAM). Find information about a set of pages in a call process or the address space of a specific process. It may change the access protection of a set of pages bound to the physical address of the call process.

Heap Functions

The system provides a default heap for each process. Private heaps can help applications that make frequent allocations from the heap perform better. A private heap is a block of one or more pages in the caller process’s address space. After constructing the private heap, the process manages the memory in it via operations like HeapAlloc and HeapFree.

File Mapping

The association of file content with a piece of visible address space in the process is known as a file map. To track this relationship, the system creates a file map maker (also known as a category object). File view is the physical address area are used for the file content access process. The process may use both input and outgoing sequences (I/O) thanks to the file map. It also allows the process to work effectively with large data files, such as websites, without requiring the entire file to be mapped to memory. Files with a memory map can be used with many processes to exchange data.

The memory management in the operating system is to control or maintain the main memory and transfer processes from the primary memory to disk during execution. Memory management keeps track of all memory locations, whether the process uses them or not. Determines how much memory should be allocated to each process. Specifies how much memory each process should be given. It decides which processes will be remembered and when. It tracks when memory is released or when it is shared and changes the status accordingly.

Windows Memory Management

Microsoft Windows has its own virtual address space for each 32-bit process, allowing up to 4 gigabytes of memory to be viewed. Each process has 8-terabyte address space on 64-bit Windows. All threads have access to the visible address space of the process. Threads, on the other hand, do not have access to the memory of another process, which protects one process from being damaged by another.

Architecture for 32-bit Windows: The automatic configuration of the 32-bit Windows Operating System (OS) allocates 4 GB (232) of accessible memory space to the kernel and user programs equally. With 4 GB physical memory available, the kernel will receive 2 GB and the app memory will receive 2 GB. Kernel-mode address space is shared by all processes, but application mode access space is provided for each user process.

Architecture for 64-bit Windows: The automatic configuration of the 64-bit Windows Operating System (OS) allocates up to 16 TB (254) of accessible memory space to the kernel and user programs equally. As 16 TB real memory is available, the kernel will have 8 TB of virtual address (VA) space and user application memory will have 8 TB of VA space. Visible address space in the kernel is allocated for all processes. Each 64-bit functionality gets its place, but each 32-bit system works on a 2 GB (Windows) virtual machine.

Virtual Address Space

The process’ visible address space is the range of memory addresses that you can use. The address area of ​​each process is private, and can only be accessed through other processes if it is shared.

A virtual address does not reflect the actual location of an object in memory; instead, the system stores a table for each process, which is an internal data structure that converts visible addresses into local addresses. The program converts the virtual address into a local address every time the chain refers to it.

The virtual address area of Windows is divided into two parts: one for process use and the other for system usage.

Virtual Memory Functions

A process can alter or determine the state of pages in its virtual address space using virtual memory functions.

The width of the visible address space is reserved for the process. Although saving address space does not provide material storage, it prevents scope from using other sharing processes. It does not affect other active address spaces for other processes. Page storage reduces unnecessary use of virtual storage while allowing the process of setting aside part of its address space for the flexible data structure. As required, the procedure can provide a physical repository for this area.

Provide a set of cached pages in the address of the process so that only a shared process can access real storage (either RAM or disk).

For the most dedicated pages, specify read/write, read-only, or no access. This differs from the general distribution procedures, which often provide read/write access to the pages.

Release a set of saved pages, making the visible address set accessible for the following call process sharing actions.

We can withdraw a group of committed pages, freeing up portable storage that can be assigned to any process in the future.

To prevent the program from changing pages in the file, lock one or more memory pages bound to the virtual memory (RAM). Find information about a set of pages in a call process or the address space of a specific process. It may change the access protection of a set of pages bound to the physical address of the call process.

Heap Functions

The system provides a default heap for each process. Private heaps can help applications that make frequent allocations from the heap perform better. A private heap is a block of one or more pages in the caller process’s address space. After constructing the private heap, the process manages the memory in it via operations like HeapAlloc and HeapFree.

File Mapping

The association of file content with a piece of visible address space in the process is known as a file map. To track this relationship, the system creates a file map maker (also known as a category object). File view is the physical address area are used for the file content access process. The process may use both input and outgoing sequences (I/O) thanks to the file map. It also allows the process to work effectively with large data files, such as websites, without requiring the entire file to be mapped to memory. Files with a memory map can be used with many processes to exchange data.

Понравилась статья? Поделить с друзьями:
  • Команда temp в командной строке windows 10
  • Коды для удаления приложений windows 10
  • Количество видов оформления интерфейса в windows 7
  • Команда для автозапуска программ windows 10
  • Коды для выполнить в windows 10