Mikrotik Ninja
3.24K subscribers
326 photos
6 videos
54 files
1.11K links
Канал по новым компьютерным технологиям и защите компьютерных программ


Блог http://bubnovd.net
https://medium.com/@dbubnov
https://xakep.ru/author/bubnovd/
Мысли неглупых людей https://t.me/channel1name
Книги https://t.me/mreadninja
Download Telegram
Большинство из нас пользуется 64-разрядными системами. В таких системах процессы работают с адресным пространством размером 2^64 байт (16 эксабайт или 16 млн ТБ). Многие из читателей имеют столько памяти в системе? Как получается, что процесс видит 16 ЭБ памяти, когда в системе её намного меньше? Как получается, что относительно небольшая физическая память так интенсивно используется программами и не позволяет читать чужие данные? Как распределяется между процессами физическая память?

На эти вопросы отвечает книга Operating Systems. Three easy pieces. До её прочтения я слабо представлял себе работу ОС. А теперь представляю ещё хуже, зато более системно 😁 Вы ведь знакомы с этим чувством, когда начинаешь изучать что-то новое и открываешь новую пропасть в своих знаниях, которую придется заполнять ещё долгие годы?

Во время чтения книги появилась идея написать серию постов о работе ОС. Хочу начать с виртуальной памяти, так как мне её работа показалась очень элегантной и эффективной.

Кратко и маленькими частями эти посты будут выходить в этом телеграм канале, а потом появится один большой пост в блоге


Итак,

=== Виртуальная память в Linux. Часть 0 ===

Чем хороша виртуализация памяти: прозрачность, эффективность, изоляция

- Прозрачность (transparency ). Virtual memory реализована операционной системой абсолютно незаметно для процессов. Программы не знают что там происходит с памятью. Они думают, что владеют всей памятью в системе и не заботятся об изоляции от других проессов

- Эффективность (efficiency). Программисту не нужно думать о том, как и где хранить переменные, потому что виртуальное адресное пространство огромно. Жизнь становится проще, если не нужно задумываться о работе с низкоуровненвыми абстракциями. ОС делает виртуализацию максимально эффективной по времени и размеру. Благодаря работе с железом ОС делает этот процесс ещё лучше (MMU, TLB)

- Изоляция. ОС обеспечивает изоляцию адресных пространств. Один процесс не может обратиться к памяти другого. Спцеиально или из-за бага


#OS #OSTEP #memory #vm
=== Виртуальная память в Linux. Часть 1.1 ===

Давным давно системы были однозадачными и вся память была доступна одному процессу. Не надо было беспокоиться о приватности данных и безопасности. Потом наступила эра многозадачности: компьютером стали пользоваться одновоременно несколько человек. Каждый запускает свои программы. Ранние реализации просто отдавали всю память процессу, а когда приходил другой процесс - содержимое памяти первого сбрасывалось на диск и в неё загружались данные нового процесса.

Очевидно, что запись и чтение с диска - операция затратная и куча времени бесполезно расходовалась на это. Нужен был новый, более эффективный
процесс.

#OS #OSTEP #memory #vm
=== Виртуальная память в Linux. Часть 1.2 ===

Этот процесс называется Sharing. Это использование одной физической памяти одновременно несколькими процессами. У каждого процесса есть своё адресное пространство

Адресное пространство (Address Space) - память, которую видит процесс. В 32 разрядных системах это 2^32 байт (4 ГБ), в 64 разрядных 2^64 Б (16 ЭБ). Очевидно, что физическая память не имеет отношения к объёму адресного пространства. Не у каждого из нас ведь есть 16 ЭБ RAM. Это всего лишь абстракция, предоставляемая операционной системой

Сам Address Space делится на три части:
- Code. Код процесса

- Heap. Куча. Начинается сразу после кода и растет вниз (от stack к 2^32 в 32-разрядных системах)

- Stack. Стек. Начинается с конца адресного простарнства и растет вверх (с 2^32 в 32-разрядных системах до конца кучи)

#OS #OSTEP #memory #vm
=== Виртуальная память в Linux. Часть 1.3 ===

Как видно на картинке процесс считает, что адресация его памяти начинается с ноля. КАЖДЫЙ процесс так считает. И все они одновременно работают в физической памяти

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

#OS #OSTEP #memory #vm
- Stack. Начинается с конца адресного пространства и растет вверх. Стек управляется компилятором имплицитно. Поэтому он называется автоматической памятью. Когда функция выполнилась, она вернула значение и компилятор деаллоцировал память. В стеке хранятся локальные переменные, параметры функций и возвращаемые адреса


Понятно, почему стек и хип разнесли в разные стороны адресного пространства. Так они могут расти, не мешая друг другу

Конечно, адресное пространство - всего лишь абстракция, предоставляемая процессам со стороны ОС. Вся память, которую видит процесс - абстракция. Поэтому она и называется виртуальной памятью (Virtual Memory). Адреса виртуальной памяти указывают на память физическую. Преобразованием виртуальных адресов в физические занимается ОС с помощью различных аппаратных ухищрений

#OS #OSTEP #memory #vm
Каждое ядро CPU имеет два регистра: base (базовый) и bound (граничный).

- В base регистре лежит смещение. Физический адрес = виртуальный адрес + base

- bound регистр указывает на границу физической памяти процесса. Если адрес, к которому обращается процесс выходит за границу, указанную в bound регистре, вызывается исключение и процесс завершашется

Пример:
Address Space Size 4 KB
Loaded in phys address 16 KB
• Virtual Address 0 → Physical Address 16 KB
• VA 1 KB → PA 17 KB
• VA 3000 → PA 19384
• VA 4400 → Fault (out of bounds)

Регистры - часть CPU и работу по релокации делает CPU. Часть процессора, которая занимается работой с памятью называется Memory Management Unit (MMU). Чем сложнее эта работа, тем более сложным будет MMU

Проблемы:
- При создании процесса ОС должна найти место в физ памяти для размещения там адресного пространства процесса. То есть нужно иметь список свободного места (free list)

- После завершения процесса нужно освободить его место в физ памяти и записать обратно в free list

- У ЦПУ только одна пара бэйз-баунд регистров. При конекст свитчинге нужно сохранить куда-то бэйз и баунд текущего процесса и считать откуда-то эти регистры нового процесса. Procss Control Block (PCB)

- Доступ к регистрам привилигрованный. Только кернел режим ОС может ими управлять. Если бы это мог делать обычный процесс, он бы мог перезаписать значения регистров и читать/писать чужую память

- Мы смогли создать независимую память для каждого процесса и изолировать её. Но т.к. аллоцируем всё адресное пространство, то аллоцируемое, но неиспользуемое место между хипом и стеком простаивает впустую, как видно на рис. 15.2. Это называется внутренней фрагментацией

В следующей части попробуем решить эти проблемы

#OS #OSTEP #memory #vm
Итак, сегментация позволила нам не расходовать впустую огромные куски памяти с минимальным оверхедом на трансляцию

Проблема заключается в том, что сегментация все еще недостаточно гибкая, чтобы поддерживать наше полностью обобщенное, разреженное адресное пространство. Например, после освобождения памяти от закрытых программ мы получим разреженную память как на картинке слева (это и есть внешняя фрагментация). То есть в памяти появляется много неиспользуемых дырок, которые нужно чем-то занять. Но это будет не всегда возможно из-за того, что программам будет требоваться больше места, чем есть в каждой из дырок

Другими словами, наша модель использования адресного пространства не совсем соответствует тому, как работает сегментация. Таким образом, нам необходимо найти новые решения

#OS #OSTEP #memory #vm
Операционной системе необходимы драйверы для любого устройства, которое потенциально может быть подключено к системе. Неудивительно, что драйверы устройств занимают огромную часть кода ОС. Исследования ядра Linux показали, что 70% кода - драйверы. Когда кто-то говорит, что ОС это миллионы строк кода, это значит, что ОС это миллионы строк кода драйверов. Конечно, для каждой конкретной инсталляции большинство этого кода неактивно.

Что более грустно - драйверы пишутся любителями, в отличие от основного кода ядра, написанного хакерами, в правильном смысле этого слова. Теперь понятно почему драйверы - основная причина крэша ядра

#ostep #linux #os
На самом деле в Page Table содержатся не только данные о сопоставлении виртуальных и физических страниц. Например:
- valid bit - указывает на корректность трансляции - что такая страница существует

- protection bits - уровевнь доступа (read/write/executable)

- present bit - есть ли страница в физической памяти или в свопе (swap)

- dirty bit - изменялась ли страница после её помещения в своп

- ...

Пейджинг гибкий, упрощает управление свободным пространством. С ним нет внешней фрагментации, поскольку используются страницы одинакового размера. Освободившийся физический фрейм легко занимается новой страницей того же размера. Однако пейджинг всё ещё дорогая операция и не всегда эффективная (чтобы занять 1 бит в памяти, требуется выделить целых 4 КБ на страницу)

#OS #OSTEP #memory #vm
== Виртуальная память в Linux. Часть 6. Translation Lookaside Buffer (TLB) ==

Пейджинг - тяжелая операция. Как это часто бывает с научными и техническими инновациями, в первые годы его считали неэффективным и бесполезным. Понадобилось больше десяти лет, чтобы оптимизировать его и использовать в промышленных системах.

В оптимизации этого процесса помогла, как часто бывает, аппаратная составляющая. Page Table в отдельную структуру внутри CPU - Translation Lookaside Buffer. Это ещё одна функция уже известного нам MMU.

Кроме этого, для оптимизации работы Page Table используются разные её организации: линейная, уменьшенная, инвертированная

#OS #OSTEP #memory #vm