Байт выделенной виртуальной памяти

Обновлено: 07.07.2024

Монитор производительности – это основное средство для отслеживания производительности системы и определения узких мест. Чтобы запустить монитор производительности, нажмите кнопку Пуск, выберите пункт Панель управления, Администрирование, а затем дважды щелкните Монитор производительности.

Далее представлена сводка по некоторым важным счетчикам и предоставляемым им сведениям:

· Память, байт выделенной виртуальной памяти. Этот счетчик представляет меру спроса на виртуальную память.Он показывает, сколько байтов было выделено процессам и для какого объема памяти ОС выделила рамку страницы ОЗУ или раздел страницы в файле подкачки (или и то, и другое). Если значение Байт выделенной виртуальнойпамяти превышает объем доступной ОЗУ, подкачка используется более интенсивно, а размер файла подкачки также увеличивается. В определенный момент использование файла подкачки начинает сильно влиять на производительность.

· Процесс, рабочий набор, всего. Этот счетчик представляет меру активно используемой виртуальной памяти. Он показывает, сколько требуется оперативной памяти, чтобы вся используемая виртуальная память для всех процессов размещалась в ОЗУ. Это значение всегда кратно 4096 – размеру страницы в Windows. Если объем требуемой виртуальной памяти превышает доступный объем ОЗУ, ОС изменяет часть виртуальной памяти процесса, расположенную в рабочем наборе, для оптимизации использования ОЗУ и сокращения применения файла подкачки.

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

· Память, обмен страниц/сек. Этот счетчик очень часто неправильно интерпретируют.Большое его значение необязательно подразумевает, что узкие места производительности возникают из-за недостатка ОЗУ. ОС не использует подкачку для записи страниц из-за слишком большого объема выделенной памяти.

· Память, вывод страниц/сек. Этот счетчик показывает, сколько страниц виртуальной памяти записывались в файл подкачки для освобождения страниц ОЗУ для других целей каждую секунду.Этот счетчик необходимо отслеживать, если вы подозреваете, что узкое место – это подкачка. Даже если значение счетчика Байт выделенной виртуальной памяти больше объема ОЗУ, проблем с производительностью из-за недостатка оперативной памяти не будет, если значение счетчика "Вывод страниц/сек" небольшое или равно нулю в течение большей части времени.

· Память, байт кэш-памяти,Память, байт в невыгружаемом пуле,Память, байт в выгружаемом пуле,Память, всего байт системного кода,Память, всего байт системных драйверов.Сумма этих счетчиков представляет меру того, какая часть из 2 ГБ общей части виртуального адресного пространства объемом 4 ГБ фактически используется. Используйте эти значения, чтобы определить, достигает ли ваша система одно из архитектурных ограничений, описанных ранее.

· Память, доступно МБ. Этот счетчик представляет меру того, сколько оперативной памяти доступно для удовлетворения спроса на виртуальную память (новые запросы выделения или восстановления страницы из файла подкачки).Если ОЗУ недостаточно (например, значение счетчика "Байт выделенной виртуальной памяти" больше объема ОЗУ), ОС попытается сохранить определенную часть оперативной памяти доступной для непосредственного применения, копируя страницы виртуальной памяти, которые не используются активно, в файл подкачки. Поэтому этот счетчик не достигнет нуля, что необязательно является признаком недостатка оперативной памяти в системе.

В диспетчере задач есть несколько вкладок про память, в том числе:

Подскажите в чем разница между ними?

When RAM is in short supply (for example, Committed Bytes is greater than installed RAM), the operating system will try to keep a certain fraction of installed RAM available for immediate use by copying virtual memory pages that are not in active use to the pagefile. Therefore, this counter will not reach zero and is not necessarily a good indication of whether your system is short of RAM.

А дальше они говорят, что когда памяти на железе немножечно, то винда неиспользуемую чать памяти копирует на диск в pagefile.sys (свопник) и помечает её как свободную НА ЖЕЛЕЗЕ. Т.е. свободно памяти на железе становится больше, и если каму ещё памяти нужно - то она на железе ему выделяется.

Но все процессы думают что у них памяти воз и маленькая тележка - хотя на самом деле у них воз в pagefile.sys и маленькая тележка на железке.

А дальше они говорят, что когда памяти на железе немножечно, то винда неиспользуемую чать памяти копирует на диск в pagefile.sys (свопник) и помечает её как свободную НА ЖЕЛЕЗЕ. Т.е. свободно памяти на железе становится больше, и если каму ещё памяти нужно - то она на железе ему выделяется.

Но все процессы думают что у них памяти воз и маленькая тележка - хотя на самом деле у них воз в pagefile.sys и маленькая тележка на железке.

Теперь все понятно.

А дальше они говорят, что когда памяти на железе немножечно, то винда неиспользуемую чать памяти копирует на диск в pagefile.sys (свопник) и помечает её как свободную НА ЖЕЛЕЗЕ. Т.е. свободно памяти на железе становится больше, и если каму ещё памяти нужно - то она на железе ему выделяется.

Но все процессы думают что у них памяти воз и маленькая тележка - хотя на самом деле у них воз в pagefile.sys и маленькая тележка на железке.

Теперь все понятно.

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

Например, много памяти занимает код приложений, включая тыщи dll. Сектора диска проецируются на страницы ОЗУ, это запоминается в декрипторах страниц (ставится прямое соответствие страница-сектор). Естественно, если ОС желает освободить память, зачем её эти DLL копировать в файл подкачки? Она просто освобождает память, и всё. А когда нужно, опять подгружает эти сектора с диска.

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

Теперь все понятно.

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

Например, много памяти занимает код приложений, включая тыщи dll. Сектора диска проецируются на страницы ОЗУ, это запоминается в декрипторах страниц (ставится прямое соответствие страница-сектор). Естественно, если ОС желает освободить память, зачем её эти DLL копировать в файл подкачки? Она просто освобождает память, и всё. А когда нужно, опять подгружает эти сектора с диска.

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

Байт в выгружаемом пуле — это размер (в байтах) выгружаемого пула. Выгружаемый пул представляет собой область виртуальной памяти системы, применяемую для объектов, которые могут быть записаны на диск, когда не используются. Счетчик "Память\\Байт в выгружаемом пуле" вычисляется не так, как "Процесс\\Байт в выгружаемом пуле", поэтому он может быть не равен значению "Процесс(_Total)\\Байт в выгружаемом пуле\\". Этот счетчик отражает только текущее, а не среднее значение.

Байт в невыгружаемом пуле — это размер (в байтах) невыгружаемого пула. Невыгружаемый пул представляет собой область виртуальной памяти системы, применяемую для объектов, которые не могут быть записаны на диск и должны оставаться в физической памяти на все время своего существования. Счетчик "Память\\Байт в невыгружаемом пуле" вычисляется не так, как "Процесс\\Байт в невыгружаемом пуле", поэтому он может быть не равен значению "Процесс(_Total)\\Байт в невыгружаемом пуле\\". Этот счетчик отражает только текущее, а не среднее значение.

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

Байт выделенной виртуальной памяти - это объем виртуальной памяти, которая была выделена (Committed) - в отличие от просто зарезервированной памяти. Выделенная память должна получить место на запоминающем устройстве (т.е. на диске), либо должна не нуждаться в дисковой памяти, поскольку оперативная память достаточно велика для того, чтобы разместить в ней выделенную память. Этот счетчик отражает текущее значение, и не является средним значением по некоторому интервалу времени.

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

Байт кэш-памяти — это размер (в байтах) части кэша системных файлов, которая в настоящий момент находится в физической памяти и активна. Счетчики "Байт кэш-памяти" и "Память\\Резидентных байт системного кэша" эквивалентны. Этот счетчик отражает только текущее, а не среднее значение.

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

--
Байт свободной памяти и обнуленных страниц памяти — это объем физической памяти в байтах, назначенной свободной памяти и обнуленным страницам памяти. Эта память не содержит кэшированные данные. Она может немедленно выделяться для процесса или использования системой.

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

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

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

Всего байт системного кода — это размер (в байтах) выгружаемого кода операционной системы, сейчас сопоставленного с виртуальным адресным пространством системы. Эта величина рассчитывается путем суммирования байтов в файлах Ntoskrnl.exe, Hal.dll, драйверах загрузки и файловых системах, загруженных Ntldr/osloader. Этот счетчик не включает код, который должен оставаться в физической памяти и не может быть записан на диск. Счетчик отражает только текущее, а не среднее значение.

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

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

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

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

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

Т.е. доступно - это с учетом файла подкачки, а свободно без учета?

Вы процитировали документацию:

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

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

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

Вы процитировали документацию:

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

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

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


Привет, Хабрахабр!

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

Конечно, многие слышали про MMU, страничные таблицы и TLB. К сожалению, материалы на эту тему обычно рассматривают аппаратную сторону этого механизма, упоминая механизмы ОС только в общих чертах. Я же хочу разобрать конкретную программную реализацию в проекте Embox. Это лишь один из возможных подходов, и он достаточно лёгок для понимания. Кроме того, это не музейный экспонат, и при желании можно залезть “под капот” ОС и попробовать что-нибудь поменять.

Любая программная система имеет логическую модель памяти. Самая простая из них — совпадающая с физической, когда все программы имеют прямой доступ ко всему адресному пространству.
При таком подходе программы имеют доступ ко всему адресному пространству, не только могут “мешать” друг другу, но и способны привести к сбою работы всей системы — для этого достаточно, например, затереть кусок памяти, в котором располагается код ОС. Кроме того, иногда физической памяти может просто не хватить для того, чтобы все нужные процессы могли работать одновременно. Виртуальная память — один из механизмов, позволяющих решить эти проблемы. В данной статье рассматривается работа с этим механизмом со стороны операционной системы на примере ОС Embox. Все функции и типы данных, упомянутые в статье, вы можете найти в исходном коде нашего проекта.

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

  • Расширение реального адресного пространства. Часть виртуальной памяти может быть вытеснена на жёсткий диск, и это позволяет программам использовать больше оперативной памяти, чем есть на самом деле.
  • Создание изолированных адресных пространств для различных процессов, что повышает безопасность системы, а также решает проблему привязанности программы к определённым адресам памяти.
  • Задание различных свойств для разных участков участков памяти. Например, может существовать неизменяемый участок памяти, видный нескольким процессам.

Аппаратная поддержка

Обращение к памяти хорошо описанно в этой хабростатье. Происходит оно следующим образом:

Процессор подаёт на вход MMU виртуальный адрес
Если MMU выключено или если виртуальный адрес попал в нетранслируемую область, то физический адрес просто приравнивается к виртуальному
Если MMU включено и виртуальный адрес попал в транслируемую область, производится трансляция адреса, то есть замена номера виртуальной страницы на номер соответствующей ей физической страницы (смещение внутри страницы одинаковое):
Если запись с нужным номером виртуальной страницы есть в TLB [Translation Lookaside Buffer], то номер физической страницы берётся из нее же
Если нужной записи в TLB нет, то приходится искать ее в таблицах страниц, которые операционная система размещает в нетранслируемой области ОЗУ (чтобы не было промаха TLB при обработке предыдущего промаха). Поиск может быть реализован как аппаратно, так и программно — через обработчик исключения, называемого страничной ошибкой (page fault). Найденная запись добавляется в TLB, после чего команда, вызвавшая промах TLB, выполняется снова.

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

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

Программная поддержка

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

Виртуальный адрес

Page Global Directory (далее — PGD) — таблица (здесь и далее — то же самое, что директория) самого высокого уровня, каждая запись в ней — ссылка на Page Middle Directory (PMD), записи которой, в свою очередь, ссылаются на таблицу Page Table Entry (PTE). Записи в PTE ссылаются на реальные физические адреса, а также хранят флаги состояния страницы.


То есть, при трёхуровневой иерархии памяти виртуальный адрес будет выглядеть так:

Значения полей PGD, PMD и PTE — это индексы в соответствующих таблицах (то есть сдвиги от начала этих таблиц), а offset — это смещение адреса от начала страницы.

В зависимости от архитектуры и режима страничной адресации, количество битов, выделяемых для каждого из полей, может отличаться. Кроме того, сама страничная иерархия может иметь число уровней, отличное от трёх: например, на x86 нет PMD.

Для обеспечения переносимости мы задали границы этих полей с помощью констант: MMU_PGD_SHIFT, MMU_PMD_SHIFT, MMU_PTE_SHIFT, которые в приведённой выше схеме равны 24, 18 и 12 соответственно их определение дано в заголовочном файле src/include/hal/mmu.h. В дальнейшем будет рассматриваться именно этот пример.

На основании сдвигов PGD, PMD и PTE вычисляются соответствующие маски адресов.


Эти макросы даны в том же заголовочном файле.

Для работы с виртуальной таблицами виртуальной памяти в некоторой области памяти хранятся указатели на все PGD. При этом каждая задача хранит в себе контекст struct mmu_context, который, по сути, является индексом в этой таблице. Таким образом, к каждой задаче относится одна таблица PGD, которую можно определить с помощью mmu_get_root(ctx).

Размер страницы

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

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

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

Отдельного внимания заслуживают так называемые большие страницы: huge pages и large pages [вики] .

Платформа Размер обычной страницы Размер страницы максимально возможного размера
x86 4KB 4MB
x86_64 4KB 1GB
IA-64 4KB 256MB
PPC 4KB 16GB
SPARC 8KB 2GB
ARMv7 4KB 16MB

Действительно, при использовании таких страниц накладные расходы памяти повышаются. Тем не менее, прирост производительности программ в некоторых случаях может доходить до 10% [ссылка] , что объясняется меньшим размером страничных директорий и более эффективной работой TLB.

В дальнейшем речь пойдёт о страницах обычного размера.

Устройство Page Table Entry

В реализации проекта Embox тип mmu_pte_t — это указатель.
Каждая запись PTE должна ссылаться на некоторую физическую страницу, а каждая физическая страница должна быть адресована какой-то записью PTE. Таким образом, в mmu_pte_t незанятыми остаются MMU_PTE_SHIFT бит, которые можно использовать для сохранения состояния страницы. Конкретный адрес бита, отвечающего за тот или иной флаг, как и набор флагов в целом, зависит от архитектуры.

  • MMU_PAGE_WRITABLE — Можно ли менять страницу
  • MMU_PAGE_SUPERVISOR — Пространство супер-пользователя/пользователя
  • MMU_PAGE_CACHEABLE — Нужно ли кэшировать
  • MMU_PAGE_PRESENT — Используется ли данная запись директории

Можно установить сразу несколько флагов:

Здесь vmem_page_flags_t — 32-битное значение, и соответствующие флаги берутся из первых MMU_PTE_SHIFT бит.

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

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

Для того, чтобы получить из виртуального адреса физический, необходимо пройти по цепочке таблиц PGD, PMD и PTE. Функция vmem_translate() и производит эти шаги.
Сначала проверяется, есть ли в PGD указатель на директорию PMD. Если это так, то вычисляется адрес PMD, а затем аналогичным образом находится PTE. После выделения физического адреса страницы из PTE необходимо добавить смещение, и после этого будет получен искомый физический адрес.

Пояснения к коду функции.
mmu_paddr_t — это физический адрес страницы, назначение mmu_ctx_t уже обсуждалось выше в разделе “Виртуальный адрес”.

С помощью функции vmem_get_idx_from_vaddr() находятся сдвиги в таблицах PGD, PMD и PTE.




Работа с Page Table Entry

Для работы с записей в таблице страниц, а так же с самими таблицами, есть ряд функций:

Эти функции возвращают 1, если у соответствующей структуры установлен бит MMU_PAGE_PRESENT

Page Fault

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

В нашей системе все страницы, к которым процесс имеет доступ, считаются присутствующими в оперативной памяти. Так, например, соответствующие сегменты .text, .data, .bss; куча; и так далее отображаются в таблицы при инициализации процесса. Данные, связанные с потоками (например, стэк), отображаются в таблицы процесса при создании потоков.

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

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

Функция page_alloc() ищет участок памяти из N незанятых страниц и возвращает физический адрес начала этого участка, помечая его как занятый. В приведённом коде virt_page_allocator ссылается на участок памяти, резервированной для выделения физических страниц, а 1 — количество необходимых страниц.
Выделение таблиц
Тип таблицы (PGD, PMD, PTE) не имеет значения при аллокации. Более того, выделение таблиц производится также с помощью функции page_alloc(), только с другим аллокатором (virt_table_allocator).

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

brk — это самый большой из всех физических адресов репозитория, данное значение необходимо для ряда системных вызовов, которые не будут рассматриваться в данной статье.
ctx — это контекст задачи, использование которого обсуждалось в разделе “Виртуальный адрес”.
struct dlist_head — это указатель на начало двусвязного списка, организация которого аналогична организации Linux Linked List.

За каждый выделенный участок памяти отвечает структура marea


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

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

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

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


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

Основную работу на себя берёт do_map_region(). Она возвращает 0 при удачном выполнении и код ошибки — в ином случае. Если во время маппирования произошла ошибка, то часть страниц, которые успели выделиться, нужно откатить сделанные изменения с помощью функции vmem_unmap_region(), которая будет рассмотрена позднее.

Рассмотрим функцию do_map_region() подробнее.

Макросы GET_PTE и GET_PMD нужны для лучшей читаемости кода. Они делают следующее: если в таблице памяти нужный нам указатель не ссылается на существующую запись, нужно выделить её, если нет — то просто перейти по указателю к следующей записи.

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

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

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

try_free_pte, try_free_pmd, try_free_pgd — это вспомогательные функции. При удалении очередной страницы может выясниться, что директория, её содержащая, могла стать пустой, а значит, её нужно удалить из памяти.

Исходный код функций try_free_pte, try_free_pmd, try_free_pgd


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

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

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

этот раздел связывает счетчики производительности с данными, возвращаемыми функциями производительности памяти, и Windows диспетчером задач.

Сведения о производительности системной памяти

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

Счетчик объектов памяти (если не указано иное) Структура вкладка "производительность" диспетчера задач для Windows Server 2008 и Windows Vista вкладка "производительность" диспетчера задач для Windows Server 2003 и Windows XP
Доступно в КБ Мемористатусекс. уллаваилфис и _ сведения о производительности.Фисикалаваилабле Вычитание значения использования, показанного в графе памяти , из физической памяти (МБ): всего Физическая память: доступно
Нет Мемористатусекс. уллтоталфис и _ сведения о производительности.Фисикалтотал Физическая память (МБ): всего Физическая память: всего
Число байтов выделенной памяти Производительность _ СВЕДЕНИЯ. Коммиттотал Система: первое значение файла подкачки (в МБ) Оплата за фиксацию: всего
Предел выделенной памяти Мемористатусекс. уллтоталпажефиле и _ сведения о производительности.Коммитлимит Система: второе значение файла подкачки (в МБ) Оплата за фиксацию: ограничение
число байт Windows 2003 и Windows XP для бесплатной & обнуленного списка страниц: этот счетчик производительности не поддерживается.
Нет Физическая память (МБ): Бесплатная Неприменимо
Нет Производительность _ СВЕДЕНИЯ. Коммитпеак Нет Плата за фиксацию: Пиковая
Нет Производительность _ СВЕДЕНИЯ. HandleCount Система: дескрипторы Итоги: дескрипторы
Нет Мемористатусекс. уллаваилпажефиле None Нет
Байт в невыгружаемом страничном пуле Производительность _ СВЕДЕНИЯ. Кернелнонпажед Память ядра: нестраничная Память ядра: нестраничная
Байт в выгружаемом страничном пуле Производительность _ СВЕДЕНИЯ. Кернелпажед Память ядра: стр. Память ядра: стр.
Байт в выгружаемом страничном пуле + байт в невыгружаемом страничном пуле Производительность _ СВЕДЕНИЯ. Кернелтотал Память ядра: всего Память ядра: всего
Процессы (объекты объектов) Производительность _ СВЕДЕНИЯ. Процесскаунт Система: процессы Итоги: процессы
Число потоков (объект "процесс ( _ всего)") Производительность _ СВЕДЕНИЯ. ThreadCount Система: потоки Итоги: потоки
Байты кэша + страницы с общим подключением в резервном и измененном списках Производительность _ СВЕДЕНИЯ. Системкаче Нет Системный кэш
байты кэша + измененный список страниц + байты резервного кэша, байты резервирования в резервном кэше — байты с нормальным приоритетом + резервный кэш, байты Windows Server 2003 и Windows XP: за исключением байтов кэша, эти счетчики производительности не поддерживают
None Физическая память (МБ): кэшировано Неприменимо

Сведения о производительности памяти процесса

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

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