TGViewer
Николай Тузов Николай Тузов @ntuzov · 16.9K subscribers
Post #898 16.1K
🖥 Виртуальная vs Физическая память

Продолжаем говорить про память. В прошлых постах мы спроектировали Stack и Heap. Но то была картина изнутри программы. Теперь поднимемся на уровень выше и посмотрим, как всё это выглядит со стороны ОС.

————

Снова надеваем каску инженера. Наша команда проектирует операционную систему, и нам поручили разобраться с менеджментом памяти — нашей ОС доступен определённый её объём, и его нужно каким-то образом распределять между процессами.

Попытка 1: Нарезаем RAM — прямой доступ

Самое простое решение — поделить физическую RAM на кусочки: программе A отдадим адреса 0x0000–0x1000, программе B — 0x1000–0x2000, и так далее.

На первый взгляд, всё работает, но... Сразу же вылезает огромный букет проблем.

1. Безопасность: Что мешает Программе А обратиться к адресу программы Б и прочитать пароли из её памяти? Ничего. А если она туда что-то запишет, то Программа Б просто сломается.

2. Изоляция и адресация: Компилятору нужно заранее знать, по каким адресам будут лежать переменные, чтобы скомпилировать код. Но мы не можем заранее знать, какие физические адреса будут свободны в момент запуска программы 🗿

🟢Очевидно, что напрямую пускать процессы к железу нельзя. Думаем дальше.

Попытка 2: Иллюзия одиночества — базовый адрес и граница

Что ж, забираем у программы прямой доступ к адресам. Мы всё ещё будем присваивать ей какую-то область, но адресуем сами. То есть, каждая программа будет думать, что ей доступна вся доступная память: от 0x0000 до capacity. К примеру, [0x0000, 0x1000]. Мы же просто добавляем соответствующее смещение и следим, чтобы программа не вылезала за свои пределы.

Допустим мы выдали программе диапазон [0x3000, 0x4000]. Сама она при этом работает с адресами [0x0000, 0x1000]. Когда программа обращается к ячейке 0x0050, мы просто добавляем к ней смещение +0x3000 и получаем адрес: 0x3050. А если она просит больше, чем ей доступно, выдаём ошибку.

Это уже лучше! Но вылезает ещё более коварная проблема — фрагментация.

Представьте, что у вас 1гб памяти, и вы запустили 500 мелких программ, которым нужно ~2мб. В итоге, ваш гигабайт будет нарезан на 500 мелких кусочков.

Далее мы закрываем половину этих программ, чтобы освободить место для одной тяжёлой программы. И вот проблема: мы освободили 250 кусочков по 2мб, но они разбросаны рандомно по всему пространству! И у нас нет ни одного свободного промежутка хотя бы в 100мб:

[== Физическая память 1 ГБ ==]

1. Память забита (по 2 МБ):
|█|█|█|█|█|█|█|█|█|█|█|█|█|█|█|

2. Закрыли половину (ДЫРЫ):
|█| |█| | |█|█| |█| |█| | |█|█|
^ ^ ^ ^ ^ ^ ^
2мб 2мб 4мб 2мб 2мб 4мб 2мб

(Суммарно места много, но оно
разбито на мелкие куски)

3. Нужен цельный кусок 100 МБ:
Требуется: |██████████|
Результат: ОШИБКА! Не влезает...


Попытка 3: Страничная организация (Paging)

Очевидно, нам нужно уметь из мелких кусочков собирать большие. Давайте будем нарезать память на одинаковые мелкие кусочки — страницы (обычно по 4 КБ), а затем маппить запрошенные программой адреса с реальными через специальную таблицу (Page Table).

То есть, ОС будет вести полный учёт — кому какая страница принадлежит и правильно сопоставлять адреса с помощью таблицы

Программа же не догадывается об этой машинерии — она всё так же работает в своём виртуальном диапазоне, [0x0000,0x2000]. Например:

1. Программа пишет по адресу 0x1050

2. ОС смотрит в таблицу и сопоставляет: виртуальный адрес 0x1050 с физическим 0x8A3050

Что это нам даёт?

Безопасность: у каждой программы своя таблица страниц — свой изолированный мир. До чужой памяти физически не дотянуться, а попытка вылезти за пределы своего пространства — ошибка. Привет, Segmentation fault! 👍

Дефрагментация: виртуальные страницы программы могут идти строго по порядку, одна за другой. А вот в физической памяти ОС может раскидать их как угодно по любым свободным промежуткам.

Готово?! Да, концептуально оно работает, но есть нюанс.. 👀

На практике мы замечаем, что наша ОС жутко тормозит — топорный программный поиск по таблице, это слишком тяжёлая операция. В следующем посте будем это оптимизирвать.

#guide #memory
  • 🔥 113
  • 👍 36
More from @ntuzov
  1. Sep 15, 2026Дописал самый большой кусок статьи про Go 1.27 — раздел про постквантовые подписи. В 1.27…
  2. Sep 13, 2026Нельзя мне браться за обзоры релизов... Вместо небольшого раздела по постквантновые подпис…
  3. Aug 27, 2026😐 Ультимативный разбор... Go 1.27? Честно, не знаю зачем я это сделал, но я сделал.. Ну п…
  4. Aug 24, 2026👴 Посоветуйте хорошего бухгалтера на аутсорс в Казахстане, в идеале в Астане Рынок у нас…
  5. Jul 25, 2026🦄 Опубликовал платформу для гайдов и первую статью https://golang.guide/ Надеюсь, вам пон…
  6. Jul 24, 2026В последние дни работаю чуть ли не по 16 часов над этим проектом — мой перфекционизм не да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →