Я просто хотел добавить / прояснить, что с точки зрения программы пользовательского пространства кусок выделенной памяти всегда выглядит смежным. Операционная система в сочетании с модулем управления памятью (MMU) CPU обрабатывает все сопоставления виртуальной памяти с физической, и программисту никогда не нужно беспокоиться о том, как обрабатывается это отображение (если, конечно, указанный программист не пишет операционная система).
Компилятор (или тот, кто пишет код на ассемблере) может обрабатывать адреса программы как начинающиеся с 0 и повышающиеся до самого большого адреса, необходимого для этой конкретной программы. Затем операционная система создает таблицу страниц для каждого процесса и использует эту таблицу для частичного декодирования физического адреса для каждой ячейки виртуальной памяти. ОС обрабатывает адрес в программе как две отдельные части: адрес страницы и смещение на этой странице. Затем MMU преобразует адрес страницы в адрес физического кадра. Обратите внимание, что «кадр» физической памяти аналогичен концептуальной «странице» с точки зрения ОС; эти два имеют одинаковый размер (например, 4096 байт).
Поскольку физическая память разделена на фреймы одинакового размера, а размер страницы совпадает с размером фрейма, вы можете узнать, какая часть вашего виртуального адреса используется в качестве местоположения страницы и сколько смещений в эту страницу. Например, если ваша ОС «выделяет» 4 гигабайта каждому процессу (как в случае с Linux), а размер вашей страницы / фрейма составляет 4096 байт, вы можете знать, что 20 бит (4 294 967 296 байт / 4096 байт = 2 ^ 20 = 1 048 576 страниц / адресов страниц) 32-битного адреса используются в качестве адреса страницы, который затем преобразуется MMU в физический адрес кадра, а оставшиеся 12 бит используются в качестве смещения для определения местоположения начала адреса с начала страницы / фрейма.
VM (темп пользователя) адрес -> страница + смещение (OS) -> фрейм + смещение (MMU) = физический адрес