Страничная адресация¶
Страничная адресация — это способ организации виртуальной памяти, при котором виртуальное адресное пространство процесса разбивается на блоки фиксированного размера, называемые страницами, а физическая память делится на блоки того же размера, называемые кадрами (или страничными блоками, page frames). Соответствие между виртуальными и физическими адресами устанавливается с помощью таблиц страниц, которые хранятся в оперативной памяти и управляются операционной системой. Страничная адресация является основой для реализации механизмов виртуальной памяти, защиты памяти и разделения памяти между процессами в современных операционных системах.
¶История
Концепция страничной адресации была впервые предложена в 1961 году в Манчестерском университете (Великобритания) в рамках проекта Atlas. Система Atlas использовала однобитовые ассоциативные регистры для ускорения трансляции адресов, что стало прообразом современных буферов ассоциативной трансляции (TLB). В 1970-х годах страничная адресация была реализована в операционных системах Multics и Unix, а также в процессорах Intel 8086 (через сегментно-страничную схему). С 1980-х годов страничная адресация стала стандартом для всех универсальных процессоров, включая архитектуры x86, ARM, RISC-V и PowerPC.
¶Принцип работы
¶Виртуальные и физические адреса
Виртуальный адрес, генерируемый процессором, делится на две части: номер виртуальной страницы (Virtual Page Number, VPN) и смещение внутри страницы (offset). Размер страницы обычно составляет 4 КБ (4096 байт) в архитектуре x86, но может быть 2 МБ, 1 ГБ или другими значениями (большие страницы, huge pages). Физический адрес также делится на номер физического кадра (Physical Frame Number, PFN) и смещение. Смещение в виртуальном и физическом адресе совпадает, так как страницы и кадры имеют одинаковый размер.
¶Таблицы страниц
Таблица страниц (page table) — это структура данных, хранящаяся в физической памяти, которая для каждой виртуальной страницы содержит запись (Page Table Entry, PTE). PTE включает:
- Номер физического кадра (PFN) — адрес, куда отображается страница.
- Бит присутствия (present bit) — указывает, находится ли страница в физической памяти.
- Бит изменения (dirty bit) — фиксирует, была ли страница записана (используется для подкачки).
- Бит обращения (accessed bit) — указывает, обращались ли к странице (используется для алгоритмов замещения).
- Бит разрешения (read/write/execute) — контролирует доступ.
- Бит пользовательского режима (user/supervisor) — определяет, может ли процесс обращаться к странице.
В современных системах таблицы страниц имеют многоуровневую структуру (например, 4 уровня в x86-64: PML4, PDPT, PD, PT) для экономии памяти, так как большая часть виртуального адресного пространства не используется. Каждый уровень хранит указатели на следующий уровень, а на последнем уровне находятся PTE.
¶Трансляция адресов
Процессор при обращении к памяти выполняет следующие шаги:
- Извлекает VPN из виртуального адреса.
- Проходит по многоуровневой таблице страниц, начиная с корневого каталога (адрес которого хранится в регистре CR3 в x86).
- На каждом уровне считывает запись, проверяет бит присутствия. Если страница отсутствует (page fault), генерируется исключение, и операционная система загружает страницу с диска.
- На последнем уровне получает PFN, объединяет его со смещением и формирует физический адрес.
Для ускорения трансляции используется буфер ассоциативной трансляции (TLB) — кэш, хранящий недавно использованные соответствия VPN→PFN. Если TLB попадание (hit), трансляция занимает 1-2 такта; если промах (miss), требуется до 4-5 обращений к памяти (для 4-уровневой таблицы).
¶Классификация и виды
¶По размеру страниц
- Стандартные страницы (4 КБ) — наиболее распространённый размер, используется в большинстве ОС (Linux, Windows, macOS).
- Большие страницы (2 МБ, 1 ГБ) — применяются для приложений с большими объёмами памяти (базы данных, виртуализация, научные расчёты), уменьшают количество записей в TLB и снижают накладные расходы на управление таблицами.
- Смешанные страницы — современные процессоры поддерживают несколько размеров одновременно, что позволяет ОС выбирать оптимальный размер для каждого региона памяти.
¶По способу управления
- Одноуровневая таблица — простая, но неэффективная для больших адресных пространств (использовалась в ранних системах).
- Многоуровневая таблица — стандарт для 64-битных архитектур, позволяет экономить память за счёт того, что неиспользуемые части адресного пространства не требуют выделения таблиц.
- Инвертированная таблица страниц — хранит одну запись на каждый физический кадр, а не на каждую виртуальную страницу; используется в некоторых архитектурах (например, PowerPC) для экономии памяти при малом объёме физической памяти.
¶По типу адресации
- Страничная адресация без сегментации — чистая страничная модель, где виртуальное адресное пространство едино (например, в ARM64).
- Сегментно-страничная адресация — комбинация сегментации и страничной адресации (например, в x86-32 в защищённом режиме), где сначала виртуальный адрес преобразуется в линейный через сегмент, а затем линейный — в физический через страницы.
¶Устройство и характеристики
¶Аппаратная поддержка
Страничная адресация требует аппаратной поддержки со стороны процессора. Ключевые компоненты:
- Блок управления памятью (MMU) — аппаратный модуль, выполняющий трансляцию адресов.
- TLB — быстрый кэш для трансляций, обычно реализованный как ассоциативная память (CAM) или кэш с прямым отображением.
- Регистры управления — содержат адрес корневой таблицы страниц (например, CR3 в x86, TTBR в ARM).
- Исключения page fault — генерируются при отсутствии страницы, нарушении прав доступа или ошибках таблицы.
¶Программное управление
Операционная система отвечает за:
- Создание и обновление таблиц страниц при создании процессов.
- Обработку page fault — загрузку страниц с диска, выделение физических кадров, сброс грязных страниц.
- Замещение страниц (алгоритмы LRU, FIFO, Clock) — выбор страниц для выгрузки на диск при нехватке памяти.
- Управление TLB — сброс (flush) TLB при переключении контекста или изменении таблиц.
¶Производительность
Основные факторы, влияющие на производительность страничной адресации:
- Размер TLB — чем больше TLB, тем выше вероятность попадания. Современные процессоры имеют TLB на 32–1024 записи.
- Размер страницы — большие страницы уменьшают количество записей в TLB, но увеличивают фрагментацию и потери памяти.
- Многоуровневость таблиц — увеличивает латентность при промахе TLB, но экономит память.
- Алгоритмы замещения — влияют на частоту page fault и время доступа к диску.
¶Применение
¶Виртуальная память
Страничная адресация является основой виртуальной памяти, позволяя процессам использовать адресное пространство, превышающее объём физической памяти. Страницы, к которым давно не обращались, выгружаются на диск (своп-файл или раздел подкачки), а при необходимости загружаются обратно. Это обеспечивает изоляцию процессов и защиту памяти.
¶Защита памяти
Биты в PTE (read/write/execute, user/supervisor) позволяют операционной системе контролировать доступ к памяти. Например, страницы кода могут быть только для чтения и выполнения, а страницы данных — для чтения и записи. Это предотвращает выполнение кода из стека (NX-бит) и защищает ядро от пользовательских процессов.
¶Разделение памяти
Страничная адресация позволяет нескольким процессам совместно использовать одни и те же физические страницы (например, библиотеки, разделяемую память). При этом каждый процесс имеет свою таблицу страниц, но записи указывают на одни и те же PFN.
¶Виртуализация
В системах виртуализации (например, KVM, VMware) страничная адресация используется для изоляции гостевых операционных систем. Гостевая ОС управляет своими таблицами страниц, а гипервизор использует аппаратную поддержку вложенных страниц (Intel EPT, AMD NPT) для трансляции гостевых физических адресов в реальные физические.
¶Примеры
¶Linux
В Linux страничная адресация реализована через архитектурно-зависимый код. Для x86-64 используется 4-уровневая таблица (PML4, PDPT, PD, PT). Размер страницы по умолчанию — 4 КБ, но поддерживаются большие страницы (2 МБ через hugetlbfs, 1 ГБ через transparent huge pages). ОС использует алгоритм замещения на основе LRU (list of active/inactive pages) и поддерживает свопинг.
¶Windows
В Windows (NT-ядро) страничная адресация аналогична Linux, но с некоторыми отличиями: таблицы страниц имеют 4 уровня (PML4, PDPT, PD, PT), размер страницы — 4 КБ. Windows поддерживает большие страницы (2 МБ) через API VirtualAlloc с флагом MEM_LARGE_PAGES. Управление памятью включает рабочие наборы (working sets) и алгоритм замещения на основе тактов (clock algorithm).
¶Критика и ограничения
¶Фрагментация
Страничная адресация может приводить к внутренней фрагментации, когда последняя страница процесса используется не полностью (потери в среднем составляют половину размера страницы). Для приложений с большим количеством мелких объектов (например, базы данных) это может быть существенно.
¶Накладные расходы
Многоуровневые таблицы страниц требуют нескольких обращений к памяти при промахе TLB, что увеличивает латентность доступа. Для ускорения используются TLB, предвыборка (prefetching) и аппаратные walker (автоматический обход таблиц).
¶Уязвимости
Страничная адресация может быть использована для атак, таких как Meltdown и Spectre, которые эксплуатируют спекулятивное выполнение и TLB для получения доступа к защищённой памяти. В ответ на это были разработаны аппаратные и программные меры (KPTI — Kernel Page Table Isolation).
¶Сложность управления
Операционная система должна поддерживать сложные алгоритмы замещения, управления TLB и обработки page fault, что увеличивает сложность кода ядра и может приводить к ошибкам.
¶Интересные факты
- В архитектуре x86-64 виртуальное адресное пространство составляет 48 бит (256 ТБ), хотя физические адреса могут быть до 52 бит (4 ПБ). Оставшиеся 16 бит виртуального адреса должны быть копией 47-го бита (sign extension) для обеспечения совместимости.
- Первый коммерческий процессор с поддержкой страничной адресации — Intel 80386 (1985 год), который ввёл защищённый режим с 32-битной адресацией и страничным управлением.
- В некоторых операционных системах (например, FreeBSD) используется алгоритм замещения страниц на основе двухсторонней очереди (two-handed clock), который эффективно работает при высокой нагрузке на память.
¶Источники
- Andrew S. Tanenbaum, Herbert Bos. «Современные операционные системы» (4-е издание), 2015.
- Daniel P. Bovet, Marco Cesati. «Понимание ядра Linux» (3-е издание), 2005.
- Intel Corporation. «Intel 64 and IA-32 Architectures Software Developer's Manual», Volume 3A: System Programming Guide, 2023.
- ARM Limited. «ARM Architecture Reference Manual ARMv8-A», 2022.
- John L. Hennessy, David A. Patterson. «Компьютерная архитектура: количественный подход» (6-е издание), 2017.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →


