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

Обновлено: 30.06.2024

С понятием управления паметью в ОС связаны следующие технологии:

  • Функции управления памятью в ОС
  • Типы адресов
  • Методы распределения памяти в ОС
  • Принцип кэширования данных в ОС

Содержание

Функции управления памятью в ОС

Операционная система решает следующие задачи:

  • Отслеживание свободной и занятой памяти.
  • Выделение и освобождение памяти по запросам процессов.
  • Обеспечение настройки адресов.
  • Поддержка механизма виртуальной памяти

Типы адресов

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

Символьные имена

Символьные имена присваивает пользователь при написании программы.

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

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

Физические адреса

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

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

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

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

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

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

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

Страничная адресация в Linux

В ядре Linux версии 2.4 используют трехуровневую организацию таблиц страниц. Поддерживаются три типа таблиц страниц: глобальный (Page Global Directoiy, PGD); промежуточный каталог страниц (Page Middle Directoiy, PMD); таблица страниц (Page Table).

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

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

Особенности адресации процессов и ядра

Линейное адресное пространство каждого процесса разделяют на две части: первые 3 Гбайт адресов используются в режиме ядра и пользователя, они отражают защищенное адресное пространство процесса; остальные 1 Гбайт адресов используют только в режиме ядра.

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

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

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

Сегментация в Windows

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

Страничная адресация в Windows

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




Размер линейного адреса, с которым работает система, составляет 32 бита. Из них 10 бит соответствуют адресу в каталоге страниц, еще 10 - это индекс элемента в таблице, последние 12 бит адресуют конкретный байт страницы (и являются смещением).

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

Особенности адресации процессов и ядра в Windows

Линейное адресное пространство процесса делится на две части: первые 2 Гбайт адресов доступны для процесса в режиме пользователя и являются его защищенным адресным пространством; остальные 2 Гбайт адресов доступны только в режиме ядра и отражают системное адресное пространство.

Структура адресного пространства процессов и ядра

В адресном пространстве процесса можно выделить следующие участки:

  1. первые 64 Кбайт (начиная с нулевого адреса) - это специальный участок, доступ к которому всегда вызывает ошибки;
  2. всю память между первыми 64 Кбайт и последние 136 Кбайт (почти 2 Гбайт) может использовать процесс во время своего выполнения;
  3. дальше расположены два блока по 4 Кбайт: блоки окружения потока (TEB) и процесса (PEВ);
  4. следующие 4 Кбайт - участок памяти, куда отображаются различные системные данные (системное время, значение счетчика системных часов, номер версии системы), поэтому для доступа к ним, процессу не нужно переключаться в режим ядра;
  5. последние 64 Кбайт используют для предотвращения попыток доступа за пределы адресного пространства процесса (попытка доступа к этой памяти даст ошибку).

Системное адресное пространство содержит большое количество различных участков:

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

Что такое физическая память?

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

Что такое виртуальная память?

Физическая память vs. Виртуальная память

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

Физическая память Виртуальная память
Непосредственно установленная в компьютере оперативная память. Метод управления памятью, с помощью которого для программ создается иллюзия наличия в системе (физической) памяти, гораздо больше реально установленной.
Работает быстрее. Работает медленнее.
Ограничена размером чипа ОЗУ. Ограничена размером жесткого диска.
Может напрямую обращаться к процессору. Не может напрямую обращаться к процессору.
Использует swapping. Использует paging.

Рассмотрим данные пункты:

Физическая память является фактической памятью.

Виртуальная память является логической памятью.

Физическая память быстрее виртуальной памяти.

Физическая память ограничена размером чипа ОЗУ.

Виртуальная память ограничена размером жесткого диска.

Физическая (оперативная) память использует swapping. Swapping — это концепция управления памятью, при которой всякий раз, когда системе для хранения данных некоторого процесса не хватает оперативной (физической) памяти, она берет её из вторичного хранилища (например, жесткого диска), сбрасывая на него временно неиспользуемые данные. В Linux есть специальная программа управления памятью, которая управляет этим процессом. Всякий раз, когда ОЗУ не хватает памяти, программа управления памятью ищет все те неактивные блоки данных (страницы), присутствующие в ОЗУ, которые не использовались в течение длительного времени. Когда она успешно находит подобные блоки, то перемещает их в память подкачки (например, на жесткий диск). Таким образом, освобождается пространство оперативной памяти, и, следовательно, его можно использовать для некоторых других программ, которые нуждаются в срочной обработке.

Виртуальная память использует paging. Paging — это метод выделения памяти, при котором разным несмежным блокам памяти назначается фиксированный размер. Размер обычно составляет 4 КБ. Paging всегда выполняется между активными страницами (pages).

Команды для управления памятью в Linux

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

Файл /proc/meminfo

Файл /proc/meminfo содержит всю информацию, связанную с памятью. Для просмотра данного файла используйте команду cat:


Эта команда выводит множество параметров, связанных с памятью. Чтобы получить информацию о физической памяти из файла /proc/meminfo, используйте:

$ grep MemTotal /proc/meminfo


Чтобы получить информацию о виртуальной памяти из файла /proc/meminfo, используйте:

$ grep VmallocTotal /proc/meminfo



Команда top

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


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

Команда free

Команда free отображает объем свободной и используемой памяти в системе.


Значения для каждого поля указаны в кибибайтах (КиБ).

Чтобы получить вывод в более удобочитаемом формате, используйте:



Команда vmstat

Команда vmstat — это инструмент мониторинга производительности в Linux, который предоставляет полезную информацию о процессах, памяти, операциях ввода-вывода, подкачке, диске и планировании процессора, а также приводит статистику виртуальной памяти вашей системы.

Данная тема, на первый взгляд, не является важной для системного администрирования. А скорее более полезна тем, кто занимается разработкой, отладкой или тестированием программного обеспечения (ПО) под Linux. Однако, понимание того, как устроена и функционирует система управления памятью в Linux (даже на базовом уровне). Для любого системного администратора также может быть полезным. В первую очередь для анализа производительности системы. А также для поиска решений для её увеличения и/или оптимизации.

Как устроена память в Linux?

Базовой единицей в организации памяти для систем UNIX/Linux является страница памяти. Обладающая размером от 4 Кбайт, которому соответствует объём физического пространства в оперативной или виртуальной (область подкачки на диске или другом устройстве хранения) памяти. При запуске процессов, они запрашивают у системы (т. е. у ядра посредством соответствующих системных вызовов) память для своей работы. А в ответ на это ядро выделяет для них достаточное количество страниц памяти. Виртуальная память или как её ещё называют, «резервное ЗУ» (резервное запоминающее устройство) для страниц памяти. Которые содержат, к примеру, исходный текст исполняемого приложения, представляют собой обычные исполняемые файлы на диске. Равно как и для других файлов данных резервным ЗУ являются сами файлы. Информация о том как взаимосвязаны страницы физической и виртуальной памяти хранится в соответствующих таблицах страниц памяти.

Для работы с памятью в Linux (как и в других UNIX-подобных системах) характерно такое явление как «страничный обмен» (paging). Оно заключается в том, что ядро выделяет процессам столько памяти, сколько им необходимо. В том смысле, чтобы её (памяти) всегда хватало. Это достигается за счёт расширения физической памяти за счёт виртуальной, т. е. «подкачки». Поскольку выполнение процессов должно происходить в реальной физической памяти. То ядро постоянно перемещает страницы памяти процессов между физической и виртуальной памятью. Забегая вперёд, следует отметить, что в виртуальной памяти хранятся «неактивные» страницы. Которые не задействованы процессом в данный момент, но необходимые ему для полноценной работы впоследствии.

Основные принципы управления памятью в Linux

Первое, на что следует обратить внимание, это то, что ядро старается управлять памятью таким образом, чтобы недавно используемые процессом страницы находились в физической памяти. И в свою очередь, «неактивные» или редко используемые страницы перемещаются и хранятся в виртуальной памяти в области «подкачки». Такой механизм распределения памяти называется LRU (least recently used) — замещение наиболее редко используемых страниц.

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

Когда процессу не хватает памяти, то ядро начинает искать «занятые» страницы. Которые можно использовать для «голодающего» процесса. Обычно такими страницами являются те, что давно не были использованы. Ядро проверяет их на предмет модификации каким-либо процессом. Для этого существуют определённые признаки, при последнем обращении и если изменения были, то такие страницы помечаются ядром как «грязные». Т. е. такие, которые ещё нужны процессам. Для повторного использования памяти такие страницы сначала обязательно переносятся в виртуальную память. Все же остальные страницы являются «чистыми». И поэтому ядро их использует для предоставления другим или «голодающим» процессам.

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

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

  • возвращает ссылки на эти страницы в соответствующей таблице страниц;
  • сбрасывает в нулевое значение время «неиспользования» этих страниц;
  • помечает эти страницы как «активные».

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

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

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

В Linux можно настроить параметр, который задаёт, насколько быстро ядро должно «отбирать»страницы памяти у процессов. Которым они менее нужны для процессов, которым они на данный момент необходимы. Этот параметр содержится в файле /proc/sys/vm/swappiness и по-умолчанию равен 60. Если задать его меньшим значением (например 0). То ядро будет забирать страницы процесса в самую последнюю очередь. Используя вместо этого любые другие варианты. Если это значение в пределах между 60 и 100. То страницы будут отбираться у процессов с более высокой вероятностью. Вариант с изменением данного параметра на самом деле говорит о том, что необходимо либо снизить нагрузку на систему. Адаптировав её для других менее производительных задач, либо увеличить объём ОЗУ.

Заключение

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

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