Разница между адресом физической / логической / виртуальной памяти


Я немного путаюсь в терминах физических/логических / виртуальных адресов в операционной системе (я использую Linux - open SUSE)

Вот что я понимаю:

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

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

  3. Я столкнулся с дискуссией о том, что виртуальные и логические адреса/адресное пространство-это одно и то же. Это правда?

Любая помощь глубоко ценится.

9 21

9 ответов:

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

Типы Адресов

Что касается вопроса 3:

Я столкнулся с обсуждением того, что виртуальное и логическое адреса/адресное пространство одинаковы. Это правда?

Насколько я знаю, они одинаковы, по крайней мере, в современных ОС. работает на процессорах Intel.

Позвольте мне попытаться определить два понятия, прежде чем я объясню больше:

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

Виртуальный / Логический Адрес

Виртуальный адрес-это хорошо, виртуальный адрес, ОС вместе с аппаратной схемой, называемой MMU(блок управления памятью), вводят вашу программу в заблуждение, что она работает одна в системе, у нее есть все адресное пространство (имея 32-битную систему, ваша программа будет думать, что у нее есть 4 Гб оперативной памяти; грубо говоря).

Очевидно, что если у вас одновременно запущено несколько программ (вы всегда это делаете, GUI, Init process, Shell, clock app, calendar, что угодно), это не будет работа.

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

Пример: ваш процесс может иметь переменную с именем (счетчик), которая имеет виртуальный адрес 0xff (можно себе представить...) и другая переменная с именем (oftenNotUsed), которая имеет виртуальный адрес (0xaa).

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

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

Что произойдет, если ваша программа запросит переменную (oftenNotUsed)? MMU + OS заметит этот "промах" и заберет его для вас с жесткого диска в оперативную память, а затем передаст вам, как если бы он был в адресе (0xaa); эта выборка означает, что некоторые данные, которые присутствовали в оперативной памяти, будут отправлены обратно на жесткий диск.

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

Резюме

Виртуальный адрес : адрес, который вы используете в своих программах, адрес, который ваш процессор использует для извлечения данных, не является реальным и переводится через MMU на какой-то физический адрес; у каждого есть один и его размер зависит от вашей системы (Linux под управлением 32-разрядной версии имеет адресное пространство 4 ГБ)

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

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

Следствия этой системы

    Процессы не могут получить доступ к памяти друг друга, у каждого есть свои отдельные виртуальные адреса, и каждый процесс получает разный перевод в разные области, хотя иногда вы можете посмотреть и обнаружить, что два процесса пытаются получить доступ к одному и тому же виртуальному адресу.
  • эта система хорошо работает как система кэширования, вы обычно не используете все 4 ГБ, которые у вас есть, так почему растрачивать его впустую? пусть другие делятся им и пусть они тоже им пользуются; когда вам понадобится больше, вы получите свои данные из HD и замените их, конечно, за счет.

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

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

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

Логические адреса не обязательно применяются исключительно к пользовательскому режиму. На процессорах x86 они существуют и в режиме ядра.

Я столкнулся с дискуссией о том, что виртуальные и логические адреса/адресное пространство-это одно и то же. Это правда?

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

Я имею в виду нижеприведенную базу ответов на Intel x86 CPU

Разница между логическим и виртуальным адресом

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

Селектор сегмента - это 16-битное поле, из которого первый 13-бит является индексом (который является указателем на дескриптор сегмента, находящийся в ГРТ,описанной ниже) , 1 битовое поле Ти ( Ти = 1 см. ЛДТ ти=0 см ГДТ )

Теперь селектор сегмента или, скажем, идентификатор сегмента относится к сегменту кода или сегменту данных или сегменту стека и т. д. Linux содержит одну таблицу GDT / LDT (Global / Local Descriptor Table), которая содержит 8-байтовый дескриптор каждого сегмента и содержит базовый (виртуальный) адрес сегмента.

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

1) исследует поле TI Селектор сегментов для определения дескриптора В таблице хранится дескриптор сегмента. Это поле указывает, что дескриптор является либо в GDT (в этом случае единица сегментации получает базовую линейную адрес GDT из регистра gdtr) или в активном LDT (в этом случае блок сегментации получает базовый линейный адрес этого LDT из регистра ldtr).

2) вычисляет адрес дескриптора сегмента из индексного поля сегмента. Селектор. Поле индекса: умножить на 8 (размер дескриптора сегмента), и результат добавляется к содержимому регистра gdtr или ldtr.

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

Теперь задача Pagging unit состоит в том, чтобы перевести физический адрес из виртуального адреса.

См.: понимание ядра linux, Глава 2 адресация памяти

Обычно каждый выданный адрес (для архитектуры x86)является логическим адресом, который преобразуется в линейный адрес через таблицы сегментов. После перевода в линейный адрес он затем переводится в физический адрес через таблицу страниц.
Хорошая статья, объясняющая то же самое в глубине:
http://duartes.org/gustavo/blog/post/memory-translation-and-segmentation/

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

Логическая память находится относительно соответствующей программы, т. е. (начальная точка программы + смещение)

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

В Usermode или UserSpace все адреса, видимые программой, являются виртуальными адресами. Когда в режиме ядра адреса, видимые ядром, все еще виртуальны, но называются логическими, поскольку они равны физическому + pageoffset . Физические адреса-это те, которые видит ОЗУ . С виртуальной памятью каждый адрес в программе проходит через таблицы страниц.

Когда вы пишете небольшую программу, например:

int a=10;
int main()
{
 printf("%d",a);
}   


compile: >gcc -c fname.c
>ls 
fname.o //fname.o is generated
>readelf -a fname.o >readelf_obj.txt

/readelf-это команда для понимания объектных файлов и файла executabe, который будет находиться в 0s и 1s. вывод записывается в readelf_onj.txt-файл /

`>vim readelf_obj.txt`

/* в разделе "заголовок раздела" вы увидите .данные.текст.разделы rodata вашего объектного файла. каждый начальный или базовый адрес запускается с 0000 и растет до соответствующего размера, пока не достигнет размера под заголовком "размер" - - - - > это логические адреса.* /

>gcc fname.c
>ls
a.out //your executabe
>readelf -a a.out>readelf_exe.txt
>vim readelf_exe.txt 

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

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

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

Физические адреса Адреса, используемые между процессором и памятью системы. Физические адреса являются 32-или 64-разрядными величинами; даже 32-разрядные системы могут использовать 64-разрядные физические адреса в некоторых системах. ситуации.

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

Логические адреса ядра Они составляют нормальное адресное пространство ядра. Эти адреса отображают большую часть или всю основную память и часто рассматриваются как физические адреса. На большинстве архитектуры, логические адреса и связанные с ними физические адреса отличаются только постоянным смещением. Логические адреса используют собственный размер указателя аппаратного обеспечения и, таким образом, могут быть неспособны адресовать всю физическую память на хорошо оснащенных 32-разрядных системах. Логические адреса обычно хранятся в переменных типа unsigned long или void *. Память, возвращенная из kmalloc, имеет логический адрес.

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

Если у вас есть логический адрес, макрос __pa () (определенный в) вернет связанный с ним физический адрес. Физические адреса можно сопоставить с логическими адресами с помощью функции _ _ va (), но только для страниц с низким объемом памяти.

Ссылка .