Операционные системы
Теория: Виртуальная и физическая память
Когда процесс запускается, операционная система выделяет ему адресное пространство — диапазон адресов, к которым программа может обращаться. Это пространство всегда виртуальное: процесс «думает», что владеет всей памятью компьютера — например, от 0x00000000 до 0xFFFFFFFF в 32-битной системе или до 0x7FFFFFFFFFFF в 64-битной. На деле физическая память одна, и её делят все процессы. Операционная система и процессор обеспечивают, чтобы виртуальные адреса каждого процесса отображались на реальные участки оперативной памяти или на диск, если страница временно выгружена. Так достигается изоляция: один процесс не может случайно записать данные в память другого.
В Linux каждое приложение получает своё виртуальное пространство, а ядро — собственную область. В macOS, построенной на ядре Mach, используется тот же принцип. Windows применяет аналогичную модель: каждая программа получает до 2 ТБ виртуальной памяти (в 64-битной версии), а ядро располагается в своём диапазоне. Процессоры ARM, включая Apple Silicon, реализуют ту же идею аппаратно через блок MMU.
Контроллер памяти (MMU)
MMU (Memory Management Unit) — аппаратный блок внутри процессора, который преобразует виртуальные адреса в физические. Когда процесс читает по адресу 0x00402000, MMU обращается к таблице страниц, где записано, какой участок реальной памяти этому адресу соответствует. Если сопоставления нет, возникает page fault — ошибка страницы. Ядро обрабатывает её: находит нужные данные на диске, загружает их в RAM, обновляет таблицу и продолжает выполнение.
MMU также отвечает за защиту памяти. Любая ошибка «Segmentation fault» — результат проверки доступа, выполняемой этим блоком. Если программа обращается к чужой или несуществующей странице, MMU генерирует исключение, и ядро завершает процесс. Благодаря MMU система изолирует процессы и позволяет работать с адресными пространствами гораздо большего размера, чем физическая оперативка. Именно это делает возможной многозадачность.
Страницы и таблица страниц
Чтобы упростить управление памятью, операционная система делит её на страницы (pages) — блоки фиксированного размера, обычно по 4 КБ. Возможны и крупные страницы — 2 МБ или 1 ГБ (large pages, huge pages). Одинаковый размер нужен для простоты: ядру не приходится искать фрагменты разного объёма — страницы выделяются и освобождаются целиком.
Виртуальная страница — это часть памяти в адресном пространстве процесса.
Физическая страница (frame) — соответствующий участок реальной оперативной памяти.
Таблица страниц (page table) — структура данных, где хранится, какие виртуальные страницы сопоставлены с какими физическими.
Например, у процесса есть три виртуальные страницы подряд. Первая отображена на физическую страницу 0x1A2B3000, вторая — на 0x3C4D5000, третья выгружена в swap. Когда процесс обращается к третьей, происходит page fault, ядро подгружает страницу с диска, освобождает место в RAM, обновляет таблицу и возвращает управление.
Такой механизм позволяет запускать больше процессов, чем помещается в оперативку. Каждое приложение видит собственную память, не зная, где физически лежат данные. Именно страничная организация делает возможными подкачку, кеширование и отображение файлов через mmap().
Подкачка (Swapping)
Когда оперативная память заполняется, ядро освобождает место, выгружая неиспользуемые страницы на диск. Это подкачка (swapping). Для неё используется специальный раздел или файл swap. Процессы продолжают работать, но доступ к выгруженным страницам становится медленнее — диск гораздо медленнее RAM. Если подкачка активируется слишком часто, система впадает в состояние thrashing, когда всё время уходит на обмен страницами.
Проверить использование подкачки можно командой:
или наблюдать в динамике:
Поля si и so показывают количество страниц, подгружаемых и выгружаемых каждую секунду. Рост этих значений означает нехватку оперативной памяти.
На серверах это важный показатель: по активности подкачки видно, когда система начинает работать на пределе, и стоит добавить RAM или ограничить фоновые задачи.
mmap и разделяемая память
Иногда нескольким процессам нужны одни и те же данные. Например, веб-сервер Nginx запускает несколько воркеров, которым нужен общий кеш. Чтобы не копировать данные между процессами, ядро создаёт общую область памяти (shared memory), к которой они все подключаются. Изменения, сделанные одним процессом, становятся видны остальным мгновенно — без файлов и сокетов.
Для этого в операционных системах есть системный вызов mmap(). Он связывает файл с оперативной памятью процесса, и программа может обращаться к его содержимому напрямую, как к массиву.
Когда вызывается mmap(), ядро не копирует данные, а просто создаёт отображение: страницы файла становятся страницами памяти. Если программа изменяет байт в этом участке, изменение автоматически попадает в файл. То же самое работает и в обратную сторону — другой процесс, выполнивший mmap() того же файла, сразу увидит обновлённые данные.
Это удобно, когда нужно быстро обмениваться информацией между процессами или работать с большими файлами, например в базах данных, браузерах и файловых кешах. Всё происходит в памяти, без вызовов read() и write().
Когда программа вызывает mmap.mmap(), операционная система связывает содержимое файла data.bin с памятью процесса. Теперь файл не нужно читать или записывать — он становится частью оперативной памяти. Изменение mm[0] = 42 сразу отражается в файле на диске.
Если в это же время другая программа откроет тот же файл с помощью mmap(), она увидит новое значение без дополнительных действий. Этот способ особенно полезен, когда нужно быстро изменять большие файлы или обмениваться данными между процессами без копирования.
Такой способ экономит время и ресурсы, потому что операции выполняются напрямую в памяти, а не через файловую систему.
Анализ использования памяти
Чтобы понять, как операционная система использует оперативную память, важно не просто знать команды, но и уметь читать их параметры. Анализ памяти — одна из тем, которую часто затрагивают на собеседованиях, потому что она показывает, насколько разработчик или инженер понимает устройство системы.
В Linux одной из базовых утилит является free. Она показывает общий объём оперативной памяти, сколько занято, свободно и сколько используется под кеш. Аргумент -h делает вывод «читаемым для человека» (human-readable) — вместо байт значения отображаются в мегабайтах или гигабайтах. Команда
даёт сводную таблицу с колонками total, used, free, shared, buff/cache и available. Столбец buff/cache часто вызывает вопросы: он показывает память, которую система временно использует под кеш, но при необходимости отдаст приложениям.
Более детальную информацию предоставляет файл /proc/meminfo. Это виртуальный файл, который ядро обновляет в реальном времени. Его можно просто прочитать:
или просмотреть отдельные строки с помощью grep Mem:
Здесь видно всё — от общей памяти и кешей до состояния подкачки и памяти, занятой ядром.
Чтобы понять, какие процессы потребляют больше всего ресурсов, используют команду ps. Утилита выводит таблицу с информацией о процессах. Аргумент -e означает «все процессы», -o задаёт формат вывода. В примере
pid — идентификатор процесса, comm — имя команды, %mem и %cpu показывают долю потребления памяти и процессора. Опция --sort=-%mem сортирует процессы по убыванию использования памяти, а head ограничивает вывод первыми строками. Таким образом, можно быстро увидеть десятку самых «прожорливых» процессов.
На macOS похожие задачи решают команды vm_stat и top. Первая показывает статистику виртуальной памяти — количество свободных, занятых и активных страниц. Команда
даёт базовый обзор, а
показывает текущее использование физической памяти. Аргумент -l 1 говорит top выполнить один цикл обновления, а grep PhysMem отфильтровывает строку с нужной информацией.
В Windows похожую информацию можно получить через PowerShell. Команда
выводит список процессов, отсортированных по полю WS (Working Set) — объёму оперативной памяти, который процесс удерживает в данный момент. Sort-Object сортирует по убыванию, а Select-Object -First 10 показывает первые десять строк.
Во всех этих примерах важно не просто знать команды, а понимать, что стоит за каждой цифрой. Сколько памяти реально свободно, что система считает кешем, какие процессы занимают больше всего ресурсов — всё это помогает вовремя замечать утечки, а на собеседовании показывает уверенное владение инструментами анализа производительности.
Архитектуры и различия
Во всех современных системах — Linux, macOS, Windows и ARM-платформах — принципы работы памяти одинаковы. Каждому процессу выделяется виртуальное пространство, MMU преобразует адреса, а таблицы страниц хранят соответствия между виртуальными и физическими участками. Различия — в деталях:
- Linux (x86_64) — страницы 4 КБ, поддержка больших страниц 2 МБ и 1 ГБ, адресное пространство 48 бит.
- macOS (ARM64/x86_64) — страницы 4–16 КБ, адреса 47–48 бит.
- Windows (x86_64) — те же размеры страниц, до 128 ТБ виртуальной памяти.
- ARM / Apple Silicon — страницы 4–64 КБ, четырёхуровневые таблицы.
MMU и кеш TLB выполняют одну задачу — ускоряют обращение к памяти. В любой системе основа остаётся прежней: виртуальные адреса, страницы, таблицы и подкачка, которые обеспечивают изоляцию, гибкость и многозадачность.

