Как один и тот же виртуальный адрес для разных процессов сопоставляется с разными физическими адресами
Я ознакомился с концепцией и концепцией операционной системы, и теперь я тщательно изучаю ядро Linux. У меня есть вопрос, от которого я не могу избавиться. В современных операционных системах каждый процесс имеет собственное виртуальное адресное пространство (VAS) (например, от 0 до 2 ^ 32-1 в 32-битных системах). Это дает много преимуществ. Но в реализации я в некоторых случаях смущен. Позвольте мне объяснить это, указав пример:
Скажем, мы имеем два процесса p1, p2;
p1 и p2 имеют свои собственные VASes. Адрес 0x023f4a54
сопоставляется с разными физическими адресами (PA), как это может быть? Как делается этот перевод таким образом. Я имею в виду, что я знаю механизм перевода, но я не могу понять, что тот же адрес сопоставляется с другим физическим адресом, когда наступает адресное пространство разных процессов.
0x023f4a54 in p1 VAS => PA 0x12321321
0x023f4a54 in p2 VAS => PA 0x23af2341 # (random addresses)
Ответы
Ответ 1
Спасибо за все ответы. Фактический момент, который я не знаю, заключается в том, что тот же самый виртуальный адрес разных процессов не сталкивается друг с другом физическим корреспондентом. Я нашел ответ в приведенной ниже ссылке, каждый процесс имеет свою собственную таблицу страниц.
http://tldp.org/LDP/tlk/mm/memory.html
Ответ 2
Процессор, который предоставляет виртуальную память, позволяет вам настроить сопоставление адресов памяти, поскольку ЦП видит его на адресах физической памяти, как правило, это выполняется с помощью устройства для перехвата, называемого MMU.
Ядро ОС может запрограммировать этот MMU, как правило, не до отдельных адресов, а скорее в единицах страниц (4096 байт является общим). Это означает, что MMU может быть запрограммирован на перевод, например. виртуальные адреса 0x1000-0x2000 для перевода на физический адрес 0x20000-0x21000.
ОС хранит один набор этих сопоставлений для каждого процесса, и перед тем, как он планирует выполнение процесса, он загружает это сопоставление в MMU, прежде чем переключит управление обратно на процесс. Это позволяет создавать разные сопоставления для разных процессов, и ничто не мешает сопоставлениям сопоставления одного и того же виртуального адреса с другим физическим адресом.
Все это прозрачно, насколько это касается программы, оно просто выполняет инструкции по процессору, а поскольку ЦП установлен в режим виртуальной памяти (режим выгружаемого вызова), каждый доступ к памяти переводится MMU до его выхода на физическую шину в память.
Реальные детали реализации сложны, но здесь есть некоторые ссылки, которые могут обеспечить более глубокое понимание;
Ответ 3
Ваш вопрос путает виртуальный адрес с использованием адреса в качестве способа идентификации, поэтому первым шагом к пониманию является разделение понятий.
Рабочим примером является функция библиотеки времени выполнения C sprintf()
. При правильном объявлении и вызове он включается в программу как совместно используемый объектный модуль вместе со всеми необходимыми ему функциями. Адрес sprintf
варьируется от программы к программе, потому что библиотека загружается в доступный свободный адрес. Для простой мировой мировой программы sprintf может быть загружен по адресу 0x101000. Для сложной программы, которая рассчитывает налоги, она может быть загружена на 0x763f8000 (из-за всей логики yucky, содержащейся в основной программе, перед библиотеками, на которые она ссылается). С точки зрения системы, общая библиотека загружается в память только в одном месте, но адресное окно (диапазон адресов), которое каждый процесс видит, что память уникальна для этого исполняемого файла.
Конечно, это еще более осложняется некоторыми функциями Security Enhanced Linux (SELinux), который рандомизирует адреса, на которых разные разделы программы загружаются в память, включая отображение общей библиотеки.
--- разъяснение ---
Как правильно указывает кто-то, сопоставление виртуальных адресов каждого процесса специфично для каждого процесса, в отличие от его набора файловых дескрипторов, сокетов, родительских и дочерних процессов и т.д. То есть p1 может сопоставлять адрес 0x1000 с физическим 0x710000, а p2 отображает адрес 0x1000 на ошибку страницы, а p3 сопоставляется с какой-либо разделяемой библиотекой на физическом 0x9f32a000. Виртуальное сопоставление адресов тщательно контролируется операционной системой, возможно, для предоставления таких функций, как обмен и пейджинг, а также для предоставления функций, таких как общий код и данные, и межпроцессные общие данные.
Ответ 4
Существуют две важные структуры данных, относящиеся к поисковому вызову: таблица страниц и TLB. ОС поддерживает разные таблицы страниц для каждого процесса. TLB - это только кеш таблицы страниц.
Теперь разные процессоры отличаются друг от друга. x86 напрямую обращается к таблицам страниц, используя специальный регистр CR3, который указывает на используемую таблицу страниц. Процессоры MIPS ничего не знают о таблице страниц, поэтому ОС должна работать непосредственно с TLB.
Некоторые CPU (например, MIPS) содержат идентификатор в TLB для разделения разных процессов, поэтому ОС может просто изменить регистр управления при выполнении контекстного переключателя (если только ему не нужно повторно использовать идентификатор). Другие процессоры требуют полного TLB-флеша в каждом переключателе контекста. Таким образом, в основном ОС необходимо изменить некоторые регистры управления и, возможно, необходимо очистить TLB (выполнить сброс TLB), чтобы виртуальные адреса из разных процессов отображались на любые физические адреса, которые им нужно.
Ответ 5
Это сопоставление (виртуальный адрес на физический адрес) обрабатывается ОС и MMU (см. ответ @nos); точка этой абстракции так p1 "думает", что она обращается к 0x023f4a54
, когда на самом деле она обращается к 0x12321321
.
Если вы вернетесь к своему классу о том, как программы работают на уровне машинного кода, p1 будет ожидать, что всякая переменная/функция/что-то будет находиться в одном месте (например, 0x023f4a54
) каждый раз при загрузке. Отображение физической привязки к виртуальному адресу обеспечивает эту абстракцию. В действительности, он не всегда будет загружаться на один и тот же физический адрес, но вашей программе все равно, пока он находится в том же виртуальном адресе.