Общие сведения о виртуальном адресе, виртуальной памяти и подкачке

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

Виртуальная память

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

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

Кстати, мой Mac говорит, что у меня 8 ГБ физической памяти и 8 ГБ виртуальной памяти. В этом случае включает ли виртуальная машина физическую память или это объем места на жестком диске, используемого в качестве памяти? Доступно ли мне 16 ГБ памяти для моих программ?

введите описание изображения здесь

Вопрос 1:

Intel i5 имеет 36-битную адресную шину, а это означает, что вы можете адресовать 64 ГБ памяти. Допустим, я установил на свой компьютер 4 ГБ ОЗУ. Однако мои программы могут не знать о размере установленной памяти, поскольку она будет использоваться во многих различных системах с разными объемами памяти. Вот где виртуальная память становится удобной. Он абстрагирует фактический размер установленной памяти.

Однако что происходит, когда мои программы хотят получить доступ к адресу памяти 0xFFFFFFFFF? У меня установлено только 4 ГБ и, возможно, немного места в памяти HD.

У меня есть две теории на этот вопрос:

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

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

Недостатком первой теории является то, что что происходит, когда программа хочет использовать 64 ГБ памяти? Тогда нам нужно иметь 60 ГБ памяти в HD, поскольку у нас есть только 4 ГБ. Однако на снимке экрана ниже MAC говорит мне, что виртуальной памяти всего 8 ГБ.

Вопрос 2:

Как процессы помещаются в виртуальную память? Я имею в виду, имеет ли каждый процесс доступное пространство виртуальной памяти 0x0 - 0xFFFFFFFFF или существует только одно адресное пространство виртуальной памяти, в котором размещены все процессы?

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

введите описание изображения здесь

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

введите описание изображения здесь

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

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

ОС использует MMU (модуль управления памятью) для преобразования виртуального адреса в физический.

введите описание изображения здесь

Вопрос 3:

Есть ли одна большая гигантская таблица страниц, которая включает все страницы для каждого процесса, или каждый процесс имеет свою собственную таблицу страниц?

Пейджинг

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

Вопрос 4:

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

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


person Tarik    schedule 10.03.2014    source источник


Ответы (2)


Некоторые люди используют термин «виртуальная память», как если бы он был синонимом файла подкачки, поскольку файл подкачки представляет собой часть выделенной вами памяти, которая не является «реальной» памятью (то есть ОЗУ). Но большинство людей считают, что «виртуальная память» - это весь уровень абстракции, который операционная система предоставляет программам, который объединяет ОЗУ и файл подкачки.

Я не уверен, какое из этих определений поддерживает Mac OS, хотя кажется маловероятным, что на вашем компьютере не было бы выделено какой-либо выгружаемой памяти, поэтому я предполагаю, что он, вероятно, добавляет 8 ГБ выгружаемой памяти память на ваши 8 ГБ реальной оперативной памяти, в общей сложности 16 ГБ доступной (виртуальной) памяти.

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

Однако есть ограничения: операционная система может иметь ограничения на размер файла подкачки, до которого разрешено увеличиваться. Так что, если вы специально не сказали своей операционной системе сделать это, у нее, вероятно, не будет 64 ГБ общей виртуальной памяти. И даже если бы это было так, она не может выделить все 64 ГБ для каждой программы, поэтому вы, скорее всего, получите OutOfMemory ошибку до того, как ОС выделит вашей программе виртуальный адрес 0xFFFFFFFFF. (На самом деле, я не удивлюсь, узнав, что 0xFFFFFFFFF на самом деле является зарезервированным местоположением кода ошибки, похожим на 0x0.) Но поскольку адреса, о которых знает ваша программа, не имеют корреляции с истинными адресами памяти, есть вероятность, что вы в конечном итоге получил бы адрес памяти, который ваша программа считает 0xFFFFFFFFF, даже если операционная система не использует столько памяти.

Есть ли одна большая гигантская таблица страниц, которая включает все страницы для каждого процесса, или каждый процесс имеет свою собственную таблицу страниц?

Скорее всего и то, и другое ... а потом еще несколько.

  1. У каждого процесса есть собственная таблица памяти, и ОС будет активно предотвращать доступ вашей программы к адресу памяти, который не был выделен для этой таблицы.
  2. Также существует такая вещь, как общая память, поэтому два процесса, которым необходимо использовать одну и ту же информацию, могут создать область общей памяти и иметь адреса в этом пространстве памяти, доступные для обоих.
  3. Сама операционная система, очевидно, должна иметь какой-то способ отслеживать, сколько общей памяти доступно, какие адресные пространства свободны / используются, и какие блоки виртуальной памяти были выделены в какие места в ОЗУ или в файле подкачки.

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

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

person StriplingWarrior    schedule 11.03.2014
comment
Это было действительно хорошее объяснение! Спасибо. Быстрый вопрос, допустим, в физической памяти не так много места для новых выделений памяти, в этом случае некоторые страницы должны быть перенесены обратно во вторичное хранилище. Во время этого процесса страницы, которые меняются местами, могут принадлежать какому-то другому процессу (я полагаю). Итак, обнаруживает ли ОС таблицу страниц этого процесса и обновляет ли записи этих страниц как недопустимые для нового распределения для какого-то другого процесса? - person Tarik; 14.03.2014
comment
@Tarik: Да, каждый раз, когда данные меняются местами, соответствующие таблицы страниц обновляются. И когда данные запрашиваются этим другим процессом, они будут загружены обратно в память (скорее всего, в другом месте, чем было раньше), и таблица страниц будет обновлена ​​снова. - person StriplingWarrior; 14.03.2014
comment
Ваш конкретный пример (от 0x2 до 0xF23) предполагает, что виртуальная машина отображает каждый байтовый адрес, а не работает со страницами. Ясно, что было бы нелепо использовать два 64-битных (на самом деле только 48, но все же) адреса для сопоставления каждого байта, а не два 36-битных адреса страницы для каждой страницы размером 4 КБ (или 1 МБ). Я также почти уверен, что такие низкие адреса виртуальных машин запрещены / зарезервированы. - person Emmet; 14.03.2014
comment
@Emmet: Да, спасибо, что указали на это. Я как бы заморозил весь аспект страницы / смещения, и я думаю, что ваш ответ лучше объяснил. - person StriplingWarrior; 14.03.2014

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

Замечания

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

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

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

Вопрос 1

что происходит, когда мои программы хотят получить доступ к адресу памяти 0xFFFFFFFFF? У меня только 4 ГБ

В этом случае ваша «Теория 1» ближе.

VM отделяет адреса, которые ваша программа «видит» и с которыми работает - виртуальные адреса - от физических адресов. Ваши 4 ГБ памяти могут находиться на физических адресах от 0x0 до 0xFFFFFFFF (8 F), но адрес 0xFFFFFFFFF (9 F) находится в пользовательском пространстве (в канонической схеме) virtual < / em> адреса. При условии, что 0xFFFFFFFFF находится в блоке, выделенном для процесса, ЦП и ядро ​​(совместно) переведут адрес страницы 0xFFFFFF000 (предполагая, что страница размером 4 КБ, мы просто отрезаем младшие 12 бит) в реальную физическую страницу, которая могла бы иметь (почти) любой физический базовый адрес. Предположим, что физический адрес этой страницы - 0xeac000 (связь, установленная, когда ядро ​​предоставило вам виртуальную страницу 0xFFFFFF000), тогда байт по виртуальному адресу 0xFFFFFFFFF находится по физическому адресу 0x00eacfff.

Когда вы разыменовываете 0xFFFFFFFFF (при условии 4k страниц), ядро ​​«запрашивает» у CPU доступ к этому виртуальному адресу, и CPU отрезает младшие 12 битов и просматривает страницу в dTLB (буферы альтернативного преобразования виртуально-к- физические кеши сопоставления страниц; есть по крайней мере один для данных и один для инструкций). В случае попадания ЦП создает реальный физический адрес и получает значение. Если происходит промах TLB, ЦП вызывает сбой страницы, что заставляет ядро ​​обращаться к таблицам страниц (или «обходить»), чтобы определить правильную физическую страницу, и «возвращает» это значение в ЦП, который кэширует его в dTLB (очень вероятно, что он будет повторно использован почти сразу). Затем ядро ​​снова запрашивает у процессора этот адрес, и на этот раз оно завершится успешно, не инициируя обход.

Я признаю, что это описание довольно невзрачное (отражает мой собственный уровень знаний). В частности, точный способ, которым конкретный процесс идентифицируется в TLB, мне не на 100% ясен и, по крайней мере, отчасти зависит от оборудования. Раньше для каждого переключения контекста требовался полный сброс TLB, но в более поздних процессорах Intel есть 6-битное поле «PID», что означает, что сбросы, хотя и требуемые иногда, не всегда требуется при переключении контекста. Дальнейшая неуклюжесть возникает из-за моей неспособности описать многоуровневые TLB, PTE (записи таблицы страниц) и рассмотреть значение этого для кэширования данных и инструкций (хотя я знаю, что современное оборудование может видеть, возможно ли, что адрес на некотором уровне кеша одновременно с поиском TLB).

вопрос 2

Как процессы помещаются в виртуальную память? Я имею в виду, имеет ли каждый процесс доступное пространство виртуальной памяти 0x0 - 0xFFFFFFFFF или существует только одно адресное пространство виртуальной памяти, в котором размещаются все процессы?

Каждый процесс имеет собственное совершенно отдельное пространство виртуальной памяти. В этом (почти) вся суть ВМ.

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

Вопрос 3

Есть ли одна большая гигантская таблица страниц, которая включает все страницы для каждого процесса, или каждый процесс имеет свою собственную таблицу страниц?

Это, конечно, зависит от ОС, но я понимаю, что в Linux есть один многоуровневый набор таблиц страниц, где записи (PTE) помечены PID, а не отдельные для каждого- таблицы страниц процесса. Я думаю, что основная причина этого заключается в том, что многие сопоставления виртуальных и физических объектов имеют вид n: 1, а не 1: 1, поскольку все они равны 1: 1. в значительной степени нарушает основную цель виртуальной машины: подумайте об общих страницах только для чтения, содержащих инструкции для библиотек, таких как libc, или о страницах данных с копированием при записи, совместно используемых между родительским и дочерним объектами после вилки. Дублирование этих записей для каждого процесса в таблицах страниц для каждого процесса менее эффективно, чем добавление / удаление записей, относящихся к процессу, в / из общего набора таблиц страниц при создании / завершении процесса.

Где появляется диск

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

person Emmet    schedule 12.03.2014