Разница между адресом физической/логической/виртуальной памяти
Я немного запутался в терминах физических / логических / виртуальных адресов в операционной системе (я использую Linux - open SUSE)
вот что я понял:
физический адрес - когда процессор находится в системном режиме, адрес, используемый процессором, является физическим адресом.
логический адрес-когда процессор находится в пользовательском режиме, используемый адрес является логическим адресом. они в любом случае сопоставлены с некоторым физическим адресом путем добавления Базового регистра со значением смещения.Это в некотором роде обеспечивает защиту памяти.
Я столкнулся с дискуссией о том, что виртуальные и логические адреса/адресное пространство одинаковы. Это правда?
любая помощь будет высоко оценили.
9 ответов
мой ответ верен для процессоров Intel, работающих в современной системе Linux, и я говорю о процессах пользовательского уровня, а не о коде ядра. Тем не менее, я думаю, что это даст вам достаточно понимания, чтобы подумать о других возможностях
Типы Адресов
относительно вопроса 3:
Я столкнулся с дискуссией, что виртуальный и логический адреса / адресное пространство одинаковы. Это правда?
насколько я знаю они одинаковы, по крайней мере, в современных ОС, работающих поверх процессоров Intel.
позвольте мне попытаться определить два понятия, прежде чем я больше объяснять:
- Физический Адрес: адрес, где что-то физически находится в чипе ОЗУ.
- Логический/Виртуальный Адрес: адрес, который ваша программа использует для достижения своих вещей. Он обычно преобразуется в физический адрес позже аппаратным чипом (в основном, даже не CPU действительно знает об этом преобразовании).
Виртуальный/Логический Адрес
виртуальный адрес-это хорошо, виртуальный адрес, ОС вместе с аппаратной схемой, называемой MMU(блок управления памятью), обманывают вашу программу, что она работает одна в системе, у нее есть все адресное пространство (наличие 32-битной системы означает, что ваша программа будет думать, что у нее есть 4 Гб ОЗУ; грубо говоря).
очевидно, если у вас есть более одной программы, запущенной на время (вы всегда делаете, GUI, процесс инициализации, оболочка, приложение часов, календарь, что угодно), это не сработает.
Что произойдет, так это то, что ОС поместит большую часть вашей памяти программы на жесткий диск, части, которые вы используете больше всего, будут присутствовать в ОЗУ, но эй, это не значит, что у них будет адрес, который вы знаете.
пример: ваш процесс может иметь переменную с именем (counter), которая задана виртуальным адресом 0xff (imaginably...) и другая переменная с именем (oftenNotUsed), которому задан виртуальный адрес (0xaa).
Если Вы читаете сборку вашего скомпилированного кода после того, как все ссылки произошли, вы будете обращаться к ним с помощью этих адресов, но хорошо, переменная (oftenNotUsed) не будет действительно там в ОЗУ в 0xaa, она будет на жестком диске, потому что вы ее не используете.
более того, переменная (счетчик), вероятно, не будет физически в (0xff), она будет где-то еще в ОЗУ, когда ваш процессор попытается получить то, что находится в 0xff, MMU и часть ОС сделают сопоставление и получат эту переменную, откуда она действительно доступна в ОЗУ, вы даже не заметите, что ее не было в 0xff.
теперь, что произойдет, если ваша программа запрашивает переменную (oftenNotUsed)? MMU + OS заметит этот "промах" и получит его для вас с жесткого диска в ОЗУ, а затем передаст его вам, как если бы он был в адресе (0xaa); эта выборка означает, что некоторые данные, которые присутствовали в ОЗУ, будут отправлены обратно в ОЗУ Жесткий диск.
теперь представьте, что это работает для каждого процесса в системе. Все думают, что у них есть 4 ГБ ОЗУ, никто на самом деле этого не имеет, но все работает, потому что у всех есть некоторые части их программы, Доступные физически в ОЗУ, но большая часть программы находится на жестком диске. Не путайте эту часть памяти программы, помещаемой в HD, с данными программы, которые вы можете получить через файловые операции.
резюме
виртуальный адрес: адрес, который вы используете в своих программах, адрес, который ваш процессор использует для извлечения данных, не является реальным и переводится через MMU на какой-то физический адрес; у каждого есть один, и его размер зависит от вашей системы(Linux под управлением 32-бит имеет адресное пространство 4 ГБ)
физический адрес: адресу, вы никогда не достигнете, если вы работаете на ОС. Это место, где ваши данные, независимо от их виртуального адреса, находятся в ОЗУ. Это изменится, если ваши данные будут отправлены назад и вперед к жесткому диску для того чтобы приспособить больше космоса для других процессов.
все, что я упомянул выше, хотя это упрощенная версия всей концепции, это то, что называется частью управления памятью компьютерной системы.
последствия этой системы
- процессы не могут получить доступ друг к другу памяти, каждый имеет свои отдельные виртуальные адреса, и каждый процесс получает другой перевод в разные области даже хотя иногда вы можете посмотреть и обнаружить, что два процесса пытаются получить доступ к одному и тому же виртуальному адресу.
- эта система хорошо работает как система кэширования, вы обычно не используете весь 4GB, который у вас есть, так зачем тратить это? пусть другие разделяют его и пусть они используют его тоже; когда вам нужно больше, вы получите свои данные из HD и замените их, за счет, конечно.
физический адрес - когда процессор находится в системном режиме, адрес, используемый процессором, является физическим адресом.
Не обязательно верно. Это зависит от конкретного процессора. На процессорах x86, как только вы включили перевод страницы, весь код перестает работать с физическими адресами или адресами, тривиально конвертируемыми в физические адреса (кроме SMM, AFAIK, но это не важно).
логический адрес - когда процессор находится в режим пользователя используется адрес логический адрес. они в любом случае сопоставляются с некоторым физическим адресом, добавляя базовый регистр со значением смещения.
логические адреса не обязательно применяются исключительно к пользовательскому режиму. На процессорах x86 они также существуют в режиме ядра.
я столкнулся с обсуждением того, что виртуальные и логические адреса / адресное пространство одинаковы. Это правда?
Это зависит от конкретного процессора. х86 Процессоры можно настроить таким образом, чтобы сегменты не использовались явно. Они используются неявно, а их базы всегда равны 0 (за исключением сегментов локального хранилища потоков). При удалении селектора сегментов из логического адреса остается 32-разрядное (или 64-разрядное) смещение, значение которого совпадает с 32-разрядным (или 64-разрядным) виртуальным адресом. В этой упрощенной настройке вы можете считать, что они одинаковы или что логических адресов не существует. Это не так, но для большинства практических целей, достаточно хорошее приближение.
Я имею в виду ниже базу ответов на intel x86 CPU
разница между логическим и виртуальным адресом
всякий раз, когда ваша программа находится под выполнением CPU генерирует логический адрес для инструкций, которые содержат (16-битный селектор сегментов и 32-битное смещение ).В основном виртуальный (линейный адрес) генерируется с использованием логических полей адресов.
селектор сегментов - это 16-битное поле, из которого первым 13-битным является индекс (который является указателем на дескриптор сегмента находится в GDT, описанном ниже), поле 1 бит TI ( TI = 1 , см. LDT, TI=0 см. GDT)
теперь селектор сегмента или идентификатор сегмента say относится к сегменту кода или сегменту данных или сегменту стека и т. д. Linux содержит один GDT/LDT (Global / Local Descriptor Table), который содержит 8-байтовый дескриптор каждого сегмента и содержит базовый (виртуальный) адрес сегмента.
Так для каждого логического адреса, виртуальный адрес вычисляется с помощью ниже лестница.
1) исследует поле TI селектора сегмента, чтобы определить, какой дескриптор В таблице хранится дескриптор сегмента. Это поле указывает, что дескриптор либо в GDT (в этом случае блок сегментации получает базовую линейную адрес GDT из регистра gdtr) или в активном LDT (в этом случае блок сегментации получает базовый линейный адрес этого LDT из регистра ldtr).
2) вычисляет адрес дескриптора сегмента из поле индекса сегмента Селектор. Поле индекса умножается на 8 (размер дескриптора сегмента), и результат добавляется к содержимому регистра gdtr или ldtr.
3) добавляет смещение логического адреса в поле дескриптора сегмента , таким образом, получение линейного(виртуального) адреса.
теперь это работа блока разбиения на страницы для перевода физического адреса с виртуального адреса.
см.: понимание ядра linux, глава 2 Адресация Памяти
обычно каждый выданный адрес (для архитектуры x86) является логическим адресом, который преобразуется в линейный адрес через таблицы сегментов. После перевода в линейный адрес он затем переводится в физический адрес через таблицу страниц.
Хорошая статья, объясняющая то же самое в depth:
http://duartes.org/gustavo/blog/post/memory-translation-and-segmentation/
физический адрес-это адрес, который отображается блоком памяти, т. е. загружается в регистр адресов памяти. Логический адрес-это адрес, который генерируется процессором. Пользовательская программа никогда не сможет увидеть реальный физический адрес.Блок сопоставления памяти преобразует логический адрес в физический адрес. Логический адрес, созданный пользовательским процессом, должен быть сопоставлен с физической памятью перед их использованием.
логическая память относительно соответствующей программы i.e (начальная точка программы + смещение)
Виртуальная память использует таблицу страниц, которая сопоставляется с ОЗУ и диском. Таким образом, каждый процесс может обещать больше памяти для каждого процесса.
в Usermode или UserSpace все адреса, видимые программой, являются виртуальными адресами. Когда в режиме ядра адреса, видимые ядром, по-прежнему виртуальны, но называются логическими, поскольку они равны физическому + pageoffset . Физические адреса-это те, которые видит RAM . С виртуальной памятью каждый адрес в программе проходит через таблицы страниц.
когда вы пишете небольшую программу, например:
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.текстовый файл/
`>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 (), но только для страниц с низкой памятью.