---
tags: [kernel]
verified: 2026-09-06
---

# Устройство ОС — план цикла статей

## Чем этот файл является

Замысел цикла про устройство операционных систем: почему он такой, из чего состоит и чем отличается от остальной базы. Здесь живёт то, что относится к предметной области и к структуре цикла; требования к оформлению, шаблон статьи и порядок ресёрча — в [CLAUDE.md](./CLAUDE.md) и в разделе «Правила оформления заметок» в [README](./README.md).

Отдельная причина, по которой файл существует: тикеты закрываются, и порядок статей вместе с ними теряется. Карта цикла должна лежать там, где её видно и через год.

## Чем цикл отличается от остальной базы

Вся остальная база написана с позиции того, кто систему эксплуатирует: как настроено, чем вариант A отличается от варианта B, что смотреть, когда сломалось. Этот цикл смотрит на тот же материал с позиции того, кто механизм реализует, — и это не углубление той же темы, а соседний домен.

Разница видна на конкретной паре. Статья про память в Linux разбирает поведение работающей системы под давлением: страничный кэш, overcommit, OOM-killer, zram. Статья этого цикла про ту же память разбирает, как устроена карта адресного пространства, почему ядро отображено в каждый процесс и чем платят за окно прямого доступа к физической памяти. Пересечение только в терминах; вопросы разные, и ответы тоже.

Из этого следуют три особенности изложения:

- Референс — не одна система, а несколько: Linux, FreeBSD, seL4, xv6. Механизм показывают в нескольких воплощениях, потому что именно из различий видно, что в нём существенно, а что — историческая случайность одной реализации.
- Там, где выбор реален, статья заканчивается вердиктом для человека, пишущего свою ОС: что дешевле начать, что дороже переделать потом. Там, где выбора нет и всё продиктовано железом, это говорится прямо.
- Альтернативы разбираются даже тогда, когда они мертвы. Отказ от highmem, проигрыш сегментации страницам, история про «микроядра медленные» — материал, без которого сегодняшнее решение выглядит данностью, а не решением.

## Сквозные решения цикла

**Паритет трёх архитектур.** Каждый механизм разбирается в трёх воплощениях — x86-64, ARM64, RISC-V, — и ни одна архитектура не назначена основной. Причина в том, что здесь сравнение и есть содержание: переключение на стек ядра при входе — одна задача, решённая тремя разными способами (аппаратно через TSS, аппаратно через отдельный регистр указателя стека, программно через регистр-царапину), и из этих различий видно, где архитектура помогает, а где оставляет работу операционной системе. Цена решения реальна: статьи заметно длиннее, и каждый раздел приходится держать в трёх колонках вместо одной.

Исключение — статья 9: структура ядра к системе команд не привязана.

**Префикс `os-`.** Цикл не про одну ОС, но и не набор разрозненных кроссплатформенных тем: это связная серия, статьи которой ссылаются друг на друга. Префикс отмечает серию так же, как `linux-tldr-*` отмечает справочники команд, и заодно спасает от слишком общих имён вроде `stacks.md` — имя файла в этой базе обязано быть глобально уникальным.

**Тег `kernel`.** Ни один из существующих тегов не подходит статье, которая сравнивает три системы: `linux` и `freebsd` были бы неверны по смыслу, `tooling` про инструменты, `security` покрывает лишь часть тем.

## План статей

### 1. Адресное пространство: зачем трансляция и какие есть альтернативы

Страничная память связывает в один механизм три независимые задачи — релокацию, защиту и абстракцию над физической памятью, — и каждая из них решалась и решается отдельно. Пространство решений от полного отсутствия трансляции до MMU: база и предел, сегментация и её пережитки в x86-64, MPU без трансляции, изоляция средствами языка, единое адресное пространство. Статья открывает цикл, потому что без неё остальные читаются как набор рецептов.

Файл: `os-address-space-models.md`

### 2. Страничная трансляция: таблицы, TLB, разрядность

Почему дерево, а не плоская таблица и не хеш; обратные таблицы и почему проиграли. Уровни и разрядность на трёх архитектурах, канонические адреса как следствие устройства x86-64 и два регистра базы на ARM64 как альтернатива этому трюку. Формат записи и кто обновляет биты обращения и записи. TLB как место, где на самом деле находится стоимость виртуальной памяти: промах, теги адресных пространств, инвалидация в многопроцессорной системе.

Файл: `os-paging-and-tlb.md`

### 3. Карта памяти ядра: половины, прямое отображение, KASLR

Четыре независимых решения, которые обычно принимают не глядя: отображено ли ядро в адресное пространство процесса, есть ли окно прямого доступа ко всей физической памяти, где лежит образ ядра, рандомизируется ли всё это. KPTI как цена, которую вернули обратно после Meltdown. Окно прямого отображения и обе альтернативы ему — временные отображения и вырезание страниц — вместе с их ценой.

Файл: `os-kernel-memory-map.md`

### 4. Стеки: ядра, прерываний, пользовательские

Развилка, определяющая стиль всего кода ядра: свой стек на каждый поток или один на процессор. В первом случае ядро может заблокироваться где угодно, во втором всякая блокирующая операция становится конечным автоматом. Дальше — почему стек ядра нельзя растить по отказу страницы, откуда берутся отдельные стеки для исключений, чем стек главного потока отличается от стеков остальных и почему ядро собирают без красной зоны.

Файл: `os-stacks.md`

### 5. Физическая память: от карты firmware до аллокатора

Откуда ядро узнаёт, сколько в машине памяти и что трогать нельзя. Задача раскрутки: чтобы построить таблицы страниц, нужна память, чтобы выделять память — аллокатор, а чтобы аллокатор заработал — память под его метаданные. Дальше метаданные на физическую страницу и их вес, buddy и фрагментация, объектный аллокатор поверх страничного, зоны и NUMA.

Файл: `os-physical-memory.md`

### 6. Загрузка: от питания до первой инструкции ядра

Единственная часть ОС, которую нельзя отладить привычными средствами. Что гарантирует прошивка и что от неё остаётся; протоколы загрузки и то, чем они различаются по существу — какую работу берут на себя и какую оставляют ядру. Отдельный сюжет — включение трансляции: инструкция, включающая MMU, исполняется по адресу, который обязан быть осмысленным в обеих картах, и три архитектуры решают это по-разному.

Файл: `os-boot-sequence.md`

### 7. Вход в ядро и переключение контекста

Три двери — прерывание, исключение, системный вызов — и то, чем они различаются в железе. Переключение на стек ядра как одна задача с тремя решениями. Граница доверия: почему пользовательский указатель нельзя разыменовать и какая аппаратная поддержка за этим стоит. Стоимость переключения контекста и из чего она складывается; спекулятивные атаки как налог на каждый переход.

Файл: `os-kernel-entry.md`

### 8. Ядро как программа: freestanding, компоновка, ABI, выбор языка

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

Файл: `os-kernel-as-program.md`

### 9. Структура ядра: монолит, микроядро и что между

Единственное по-настоящему открытое решение цикла: остальные восемь статей разбирают механизмы, продиктованные железом. Оно же самое дорогое в переделке. Разбор спора про монолиты и микроядра по существу: что именно измеряли, что было свойством идеи и что свойством реализации. Завершается тем, как выбор модели меняет всё, разобранное в предыдущих статьях, — а значит, принимается до них, а не после.

Файл: `os-kernel-structure.md`

## Порядок написания

Нумерация задаёт логику чтения, а не очерёдность работы. Практический порядок другой:

1. Статьи 1–4 закрывают вопрос о карте памяти и модели адресного пространства — то, с чего цикл начался.
2. Статья 8 идёт следом, хотя стоит в списке восьмой: без скрипта компоновки и понимания freestanding-окружения не собрать вообще ничего.
3. Дальше 6 и 5 — загрузка и физическая память, то есть то, что делает ядро в первые миллисекунды.
4. Затем 7 — вход в ядро, после которого система начинает что-то делать.
5. Статья 9 пишется последней, хотя тема кажется вводной: она подводит итог остальным и опирается на все механизмы сразу.

## Граф зависимостей

```text
1 ──> 2 ──┬──> 3 ──┬──> 4 ──┐
          │        ├──> 6   ├──> 7
          │        ├──> 8   │
          │        └────────┘
          └──> 5 ──> 6

9 <── 1, 3, 4, 7
```

Статьи самодостаточны, но некоторые опираются на понятия из предыдущих: карту памяти невозможно обсуждать без механизма трансляции, а модели кода в статье 8 — без карты памяти.

## Продолжение цикла

Девять статей закрывают ядро темы: память, загрузка, границы, структура. За ними естественно следует второй блок, на который тикеты пока не заводятся — формулировки успеют устареть раньше, чем до него дойдут руки:

- Устройства и контроллеры прерываний: обнаружение оборудования, PCIe, APIC против GIC против PLIC, прерывания по сообщениям.
- DMA и IOMMU: адресация со стороны устройства, когерентность кэшей, изоляция недоверенного оборудования.
- Файловые системы изнутри: слой абстракции над реализациями, кэш, журналирование, копирование при записи.
- Планирование: вытесняющее против кооперативного, классы задач, инверсия приоритетов.
- Примитивы синхронизации в ядре: какой замок можно взять в каком контексте, путь от одного большого замка к мелкогранулярным, механизмы для преимущественно читающих нагрузок.

---

## Связанные заметки

- [Linux — план цикла статей](./linux-knowledge-base-plan.md) — план соседнего цикла, взятый за образец структуры
- [TLPI — База знаний](./tlpi-start.md) — та же граница ядра и пользователя, но со стороны прикладного программиста
- [Linux — ядро: сборка, модули, параметры](./linux-kernel.md) — ядро Linux с позиции администратора: конфигурация, модули, параметры
- [Адресное пространство: зачем трансляция и какие есть альтернативы](./os-address-space-models.md) — первая статья цикла: три задачи страничной памяти и пространство решений вокруг них
- [Страничная трансляция: таблицы, TLB, разрядность](./os-paging-and-tlb.md) — вторая статья цикла: формат таблиц, разрядность и уровни, стоимость промаха TLB и инвалидация
- [Стеки: ядра, прерываний, пользовательские](./os-stacks.md) — четвёртая статья цикла: модель процесса против модели прерывания, фиксированный размер стека ядра, стеки прерываний и исключений
- [Ядро как программа: freestanding, компоновка, ABI, выбор языка](./os-kernel-as-program.md) — восьмая статья цикла: freestanding-окружение, компоновка, три ABI и выбор языка
- [Карта памяти ядра: половины, прямое отображение, KASLR](./os-kernel-memory-map.md) — третья статья цикла: половины, прямое отображение, размещение образа и KASLR
- [Вход в ядро и переключение контекста](./os-kernel-entry.md) — седьмая статья цикла: три двери в ядро, граница доверия, переключение контекста и налог на переходы
- [Физическая память: от карты firmware до аллокатора](./os-physical-memory.md) — пятая статья цикла: разбор карты от прошивки, раскрутка аллокатора, метаданные на кадр, buddy и объектный аллокатор, зоны и NUMA
- [Загрузка: от питания до первой инструкции ядра](./os-boot-sequence.md) — шестая статья цикла: прошивка и что от неё остаётся, протоколы загрузки, включение трансляции, подъём вторичных процессоров и вход в пользовательское пространство
- [Структура ядра: монолит, микроядро и что между](./os-kernel-structure.md) — девятая статья цикла: единственное открытое решение — монолит против микроядра, разбор спора по числам и итог всего цикла
