Такой ароматный! Вот как Linux управляет памятью

Операционная система Linux

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

Базовые концепты

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

数据段(data segment)Содержит хранилище для программных переменных, строк, массивов и других данных. Сегмент данных разделен на две части: данные, которые были инициализированы, и данные, которые не были инициализированы. в尚未初始化的数据Это то, что мы называем BSS. Для инициализации сегмента данных требуются константы, определяемые во время компиляции, и переменные, которым требуется начальное значение при запуске программы. Все переменные в разделе BSS инициализируются 0 после загрузки.

и代码段(Text segment)Не то же самое, сегмент данных сегмента данных может быть изменен. Программа всегда изменяет свои переменные. Кроме того, многим программам необходимо динамически распределять пространство во время выполнения. Linux позволяет сегментам данных увеличиваться или уменьшаться по мере выделения и освобождения памяти. Для выделения памяти программы могут увеличивать размер сегмента данных. Есть стандартная библиотека на языке CmallocЧасто используется для выделения памяти. Дескриптор адресного пространства процесса содержит динамически выделяемую область памяти, называемую堆(heap).

Третий абзац栈段(stack segment). На большинстве машин сегмент стека будет располагаться по верхнему адресу адреса виртуальной памяти и простираться ниже (по направлению к адресному пространству 0). Например, на 32-разрядной машине x86 стек начинается с0xC0000000, что является ограничением виртуального адреса в 3 ГБ, которое разрешено видеть процессу в пользовательском режиме. Если стек выходит за пределы сегмента стека, возникает аппаратный сбой, и страница отбрасывается на одну страницу.

Когда программа запускается, область стека не пуста, вместо этого она содержит все переменные среды оболочки и командную строку, введенную в оболочку для ее вызова. Например, когда вы вводите

cp cxuan lx

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

Когда два пользователя запускают одну и ту же программу, например.编辑器(editor), то две копии программного кода редактора хранятся в памяти, но это неэффективно. Поддержка системы Linux共享文本段作как альтернатива. На рисунке ниже мы увидим два процесса A и B, которые имеют одинаковую текстовую область.

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

В дополнение к динамическому выделению памяти процессы в Linux могут内存映射文件для доступа к данным файла. Эта функция позволяет нам сопоставить файл с частью пространства процесса, и файл может быть прочитан и записан как массив байтов в памяти. Отображение файла делает произвольное чтение и запись намного проще, чем использование системных вызовов ввода-вывода, таких как чтение и запись. Доступ к разделяемым библиотекам использует этот механизм. Следующее

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

Преимущество сопоставления файлов заключается в том, что два или более процессов могут быть сопоставлены с одним и тем же файлом одновременно, а операции записи любого процесса в файл видны другим файлам. Используя сопоставленные временные файлы, память может быть разделена для нескольких потоков.提供高带宽, временные файлы исчезают после завершения процесса. Но на самом деле двух одинаковых адресных пространств не бывает, потому что каждый процесс поддерживает разные открытые файлы и сигналы.

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

Давайте обсудим метод системного вызова для управления памятью. На самом деле POSIX не определяет никаких системных вызовов для управления памятью. Однако в Linux есть свои системные вызовы памяти, основные системные вызовы следующие:

системный вызов описывать
s = brk(addr) Изменить размер сегмента данных
a = mmap(addr,len,prot,flags,fd,offset) карта
s = unmap(addr,len) удалить карту

Если обнаружена ошибка, возвращаемое значение s равно -1, a и addr — адреса памяти, len — длина, prot — бит защиты управления, flags — другие флаги, fd — дескриптор файла, а offset — адрес памяти. Смещение файла.

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

mmapиunmapСистемный вызов управляет файлом карты. Первый параметр addr в mmp определяет адрес отображения файла. Он должен быть кратен размеру страницы. Если параметр равен 0, система присваивает адрес и возвращает a. Второй параметр — это длина, которая указывает, сколько байтов необходимо отобразить. Это также кратно размеру страницы. prot определяет бит защиты отображаемого файла, бит защиты может быть помечен какЧитаемый, записываемый, исполняемый или их комбинация. Четвертый параметр, флаги, может контролировать, является ли файл закрытым или доступным для чтения, а также требуется ли адрес или просто подсказка. Пятый параметр fd — это файловый дескриптор для сопоставления. Сопоставлять можно только открытые файлы, поэтому, если вы хотите сопоставить файл, вы должны открыть файл; смещение последнего параметра будет указывать, когда файл начинается, не обязательно каждый раз с нуля.

Реализация управления памятью в Linux

Система управления памятью — одна из важнейших частей операционной системы. С первых дней вычислений мы фактически использовали больше памяти, чем есть в нашей системе.内存分配策略преодолеть это ограничение, и наиболее известными из них являются虚拟内存(virtual memory). Виртуальная память позволяет системе иметь больше памяти, разделяя виртуальную память между несколькими конкурирующими процессами. Подсистема виртуальной памяти в основном включает следующие концепции.

большое адресное пространство

Операционная система заставляет систему казаться намного больше, чем реальная физическая память, и это потому, что виртуальная память во много раз больше, чем физическая память.

Защищать

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

карта памяти

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

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

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

общая виртуальная память

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

Теперь давайте обсудим, что такое虚拟内存

Абстрактная модель виртуальной памяти

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

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

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

Для удобства трансляции виртуальные и физические адреса разделены на блоки фиксированного размера, называемые页(page). Эти страницы имеют одинаковый размер, и если страницы не одного размера, то операционной системой будет сложно управлять. Linux в системах Alpha AXP использует страницы размером 8 КБ, а Linux в системах Intel x86 использует страницы размером 4 КБ. Каждая страница имеет уникальный номер, т.е.页面框架号(PFN).

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

На рисунке выше показаны виртуальные адресные пространства двух процессов A и B, каждый со своей собственной таблицей страниц. Эти таблицы страниц сопоставляют виртуальные страницы процесса с физическими страницами в памяти. Каждая запись в таблице страниц содержит

  • 有效标志(valid flag): Указывает, допустима ли эта запись в таблице страниц.
  • номер физического страничного фрейма, описанный этой записью
  • Информация об управлении доступом, как используется страница, доступна ли она для записи и может ли выполняться код.

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

Если текущий процесс пытается получить доступ к виртуальному адресу, но не может получить к нему доступ, эта ситуация называется缺页异常, в это время виртуальная операционная система уведомит операционную систему о неправильном адресе и причине ошибки страницы.

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

пагинация по запросу

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

обмен

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

Если страница была изменена, операционная система должна сохранить содержимое страницы, чтобы к ней можно было получить доступ позже. Этот тип страницы называется грязной страницей, и когда она удаляется из памяти, она сохраняется на странице с именем交换文件в специальном файле. Доступ к файлу подкачки очень медленный по сравнению со скоростью процессора и физической памяти, и ОС должна совмещать запись страниц на диск и сохранение их в памяти для повторного использования.

Использование Linux最近最少使用(LRU)Технология устаревания страниц для справедливого выбора страниц, которые могут быть удалены из системы. Эта схема затрагивает каждую страницу в системе. Возраст страницы меняется в зависимости от количества посещений.年轻, если страницу посещают слишком мало, вероятность того, что она будет открыта换出.

Физический и виртуальный режимы адресации

Большинство многофункциональных процессоров поддерживают物理地址узор и虚拟地址концепция шаблона. В режиме физической адресации не требуются таблицы страниц, и в этом режиме процессор не пытается выполнять какую-либо трансляцию адресов. Ядро Linux связано для работы в физическом адресном пространстве.

Процессоры Alpha AXP не имеют режимов физической адресации. Вместо этого он делит пространство памяти на несколько областей и назначает двум из них физически сопоставленные адреса. Это адресное пространство ядра называется адресным пространством KSEG и содержит все адреса от 0xfffffc0000000000 и выше. Чтобы выполнить или получить доступ к данным в коде (по определению, коде ядра), связанном с KSEG, этот код должен выполняться в режиме ядра. Ссылка на ядро ​​Linux на Альфе для выполнения с адреса 0xffffffc0000310000.

Контроль доступа

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

память при необходимости访问限制. Например, память, содержащая исполняемый код, естественно, является памятью только для чтения; операционная система не должна позволять процессу записывать данные через свой исполняемый код. Напротив, страницы, содержащие данные, могут быть записаны, но инструкции, пытающиеся выполнить эту память, завершатся ошибкой. Большинство процессоров имеют как минимум два режима выполнения: режим ядра и пользовательский режим. Вы не хотите получать доступ к исполняемому пользователем коду ядра или структурам данных ядра, если только процессор не работает в режиме ядра.

Информация об управлении доступом хранится в записи таблицы страниц выше, в записи таблицы страниц, изображение выше — это PTE Alpha AXP. Битовые поля имеют следующие значения

  • V

Указывает действительный, является ли бит действительным

  • FOR

Сбой при чтении, произошел сбой при попытке прочитать эту страницу

  • FOW

Ошибка записи, произошла ошибка при попытке записи

  • FOE

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

  • ASM

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

  • GH

когда используешь单个转换缓冲区запись вместо多个转换缓冲区Подсказка для использования, когда запись отображает весь блок.

  • KRE

Код, работающий в режиме ядра, может читать страницы

  • URE

Код в пользовательском режиме может читать страницу

  • KWE

Код, работающий в режиме ядра, может записывать на страницы

  • UWE

Код, работающий в пользовательском режиме, может писать на страницу

  • номер кадра

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

В дополнение к этому, Linux использует два бита

  • _PAGE_DIRTY

Если установлено, страницу нужно записать в файл подкачки

  • _PAGE_ACCESSED

Используется Linux для пометки страниц как посещенных.

тайник

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

буферный кеш

буферный кеш содержит块设备Буфер данных, используемый драйвером.

Помните, что такое блочное устройство? Обзор здесь

Блочное устройство — это хранилище固定大小块информация об устройстве, которое он поддерживаетЧтение и (необязательно) запись данных в блоки, сектора или кластеры фиксированного размера.. Каждый блок имеет свой物理地址. Обычно размер блока составляет от 512 до 65536. Вся передаваемая информация будет连续блоков. Основная особенность блочных устройств заключается в том, что каждый блок относительно противоположен и может считываться и записываться независимо друг от друга. Обычные блочные устройстваЖесткий диск, диск Blu-ray, USB-накопитель

Блочные устройства обычно требуют меньше контактов, чем символьные устройства.

буферный кеш через设备标识符номера блоков используются для быстрого поиска блоков данных. Если данные можно найти в буферном кеше, нет необходимости считывать данные с физического блочного устройства, что обеспечивает гораздо более быстрый доступ.

кеш страницы

Кэширование страниц используется для ускорения доступа к изображениям и данным на диске.

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

кеш подкачки

В файле подкачки сохраняются только измененные (грязные страницы)

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

аппаратный кеш

Тип аппаратного кэша обычно используется в процессорах. Кэш записей таблицы страниц. В этом случае процессор не всегда читает таблицу страниц напрямую, а кэширует перевод страницы по мере необходимости. Эти转换后备缓冲区также называетсяTLB, содержащий кэшированные копии записей таблицы страниц из одного или нескольких процессов в системе.

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

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

Таблица страниц Linux

Linux предполагает, что таблицы страниц разделены на три уровня. Каждая доступная таблица страниц содержит таблицу страниц следующего уровня.

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

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

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

Распределение и освобождение страниц

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

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

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

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

размещение страниц

Распределение страниц в Linux использует хорошо известный партнерский алгоритм для выделения и освобождения страниц. Страницы распределяются по блокам в степени 2. Это означает, что он может выделить 1 страницу, 2 страницы, 4 страницы и т. д., если в системе достаточно страниц для удовлетворения спроса. Стандарт сужденияnr_free_pages> min_free_pages, если он удовлетворен, он будет искать free_area в блоке страницы необходимого размера, чтобы завершить выделение. Каждый элемент free_area имеет карту выделенных страниц и свободных блоков страниц для блоков такого размера.

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

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

Если запрашивается блок из 2 страниц, первый блок из 4 страниц (начиная с фрейма на странице 4) будет разделен на два блока из 2 страниц. Первая страница (из кадра на странице 4) будет возвращена вызывающей стороне как выделенная страница, а второй блок (из страницы на странице 6) будет поставлен в очередь как свободный блок из 2 страниц к элементу 1 области free_area. массив выше.

Освобождение страницы

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

Например, выше, если страница 1 должна быть освобождена, она объединяется с уже свободной страницей 0 и ставится в очередь в элемент 1 области free_area как свободный блок размером 2 страницы.

карта памяти

Ядро имеет два типа карт памяти:共享型(shared)и私有型(private). Частный тип используется, когда процесс хочет только читать файл, а не записывать файл.В это время частное сопоставление более эффективно. Однако любая запись на частно отображаемую страницу приведет к тому, что ядро ​​перестанет отображать страницы в этом файле. Таким образом, операция записи не изменяет файл на диске и не видна другим процессам, обращающимся к файлу.

пагинация по запросу

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

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

Linux должен найти структуру vm_area_struct, представляющую область памяти, в которой произошла ошибка страницы. Поскольку поиск в структуре данных vm_area_struct имеет решающее значение для эффективной обработки ошибок страниц, они начинаются сAVL(Adelson-Velskii和Landis)Древовидная структура связана вместе. Если виртуальный адрес, вызвавший сбой, неvm_area_structструктура, процесс получил доступ к недопустимому адресу, и Linux выдастSIGSEGVСигнал, если у процесса нет обработчика сигнала, процесс завершится.

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

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