Capstone: три мини-OS-инструмента — что строим и зачем
Вы прошли 14 модулей. От syscalls и kernel ring до vmstat и perf. Знаете, что такое процесс, как fork работает с copy-on-write, почему /proc — это не каталог, а интерфейс к kernel. Теперь нужно собрать всё это в код. Не в задачку «выучить наизусть структуру task_struct», а в реальные утилиты, которые делают то же самое, что делают системные инструменты — ps, shell, monitor — только сами и из ваших рук.
Capstone — это последний модуль курса. Здесь нет новой теории. Здесь только применение того, что уже знаете. Цель: после трёх уроков у вас в руках три рабочих инструмента и понимание, как они построены из примитивов ОС. Это знание невозможно получить чтением — только написанием.
Что мы построим
Три инструмента, каждый учит свой пласт ОС:
Каждый собирает свой кусок знаний из курса в работающий код
Каждый инструмент маленький — 150-250 строк. Но каждый — настоящий: вы запускаете его и видите, что он работает. И каждый раскрывает что-то, что нельзя получить из теории.
Зачем именно эти три
Можно было выбрать другое. Например, написать свой kernel module (но это требует kernel-headers и compile setup, не для всех платформ). Можно написать container runtime (но это deep dive в namespaces — отдельный мини-курс). Эти три выбраны потому, что каждый из них:
- Покрывает несколько модулей курса — нельзя написать mini-ps без понимания /proc, процессов, memory layout. Нельзя написать shell без fork/exec, signal handling, file descriptors.
- Запускается на любом Linux — нужен только Python 3 (или C компилятор для урока 3). Никаких прав root, никаких странных зависимостей.
- Имеет реальный аналог —
ps,bash,top. Вы напишете свою упрощённую версию и узнаете, как устроены инструменты, которыми пользуетесь каждый день.
Mapping проектов на модули курса
Стек технологий
Все три инструмента можно написать на Python 3. Это сознательный выбор:
- Низкий barrier: не нужно настраивать gcc, libc-dev, валяться с segfault.
- Высокая близость к syscalls: модули
osиsubprocess— тонкие обёртки надopen(),fork(),exec(). Python-код читается почти как C. - Понятный output: f-strings и print с format давно лучше чем
printf.
Для урока 3 (shell) опционально дам версию на C — потому что fork/exec в C это «как было задумано», и polezno хоть раз увидеть. Но если C не пишете — Python работает.
Никаких внешних зависимостей. Только stdlib. Это важно: вы должны увидеть, что весь этот функционал — из os, sys, signal, select. Никакого магического psutil (хотя в проде вы возьмёте именно его).
Архитектура каждого инструмента
Каждый из трёх инструментов следует одному паттерну:
Read state from /proc -> parse -> compute -> output
Этот паттерн повторяется во всём системном софте. top читает /proc и форматирует. iostat читает /proc/diskstats и считает diff. vmstat читает /proc/stat + /proc/meminfo. Понимание этого паттерна снимает магию с системных тулз: они не делают ничего, что не можете вы.
Что вы получите
Дам конкретно по каждому инструменту, какие умения вы возьмёте после уроков 2-4 и labs:
Из mini-ps
- Уверенное чтение
/proc/[pid]/stat,/proc/[pid]/status,/proc/[pid]/cmdline— три файла с разной структурой. - Понимание разницы между
RSSиVSZ— почему программа на 1 GB VSZ может занимать 50 MB RSS. - Базовая работа с состояниями процессов:
R,S,D,Z,T— что значит каждое. - Парсинг таких хитрых форматов как
(name)в stat, гдеnameможет содержать скобки и пробелы. - Итерация по
/proc— собрать список всех PID.
Из mini-shell
fork()черезos.fork(). Что значит «возвращает 0 у ребёнка, PID у родителя».execvp()черезos.execvp(). Что значит «заменяет образ текущего процесса».wait()черезos.waitpid(). Почему без него получаем зомби.pipe()черезos.pipe(). Как kernel связывает два процесса.dup2()черезos.dup2(). Как перенаправить stdin/stdout.- Сигналы:
signal.signal()для Ctrl+C — почему просто try/except KeyboardInterrupt мало. - Простейший парсер shell-команд: tokens, операторы (
|,>,<).
Из resource-monitor
- Чтение
/proc/statдля CPU времени по cores. - Чтение
/proc/meminfoдля total / available / cached / buffers. - Чтение
/proc/diskstatsдля read/write секторов с time-since-boot. - Diff между выборками: CPU% = (delta_user + delta_system) / delta_total.
- Threshold-based alerts и почему
time.sleep()не точен.
Структура capstone-уроков
Каждый из уроков 2-4 имеет одну структуру:
- Что строим — описание утилиты с примером output.
- Архитектура — компоненты, поток данных, диаграмма.
- Implementation — ключевые куски кода с пояснениями.
- Edge cases — что ломается и как с этим справиться.
- Попробуй сам — расширения и эксперименты.
- KnowledgeCheck — закрепление.
В labs (отдельная директория labs/) есть полные templates с TODO, expected solutions, verify-скрипты. Уроки покажут логику и подходы, labs дадут структурированный hands-on с проверкой.
Чек-лист готовности
Перед началом убедитесь:
- Доступ к Linux (нативно, WSL2 или Docker
docker run -it python:3.13 bash). - Python 3.10+:
python3 --version. Если ниже — поставьте 3.13 (большинство dist-репозиториев имеют). - Терминал, который не закроется через 5 минут idle (для shell-урока полезно).
- ~3-4 часа на всё (45-60 минут на каждый урок + labs).
Если на macOS — Linux только в Docker/VM. macOS — это не Linux, у него другой формат /proc (его там нет вовсе, есть sysctl), другие syscalls (XNU kernel). Вы можете прочитать уроки на mac, но запустить код — только на Linux.
# Если нет Linux под рукой
docker run --rm -it -v "$(pwd):/work" -w /work python:3.13 bash
# Внутри контейнера
ls /proc/1/
# должен показать: stat, status, cmdline, и ~40 других файлов
Попробуй сам
Прямо сейчас, до перехода к уроку 2:
- Откройте Linux-терминал (или Docker, как выше).
- Найдите PID своего shell:
echo $$. Получите число, например12345. - Прочитайте, что про вас знает kernel:
cat /proc/$$/status | head -20
Вы увидите:
Name: bash
Umask: 0022
State: S (sleeping)
Tgid: 12345
Ngid: 0
Pid: 12345
PPid: 5432
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 4 24 27 30 46 100
VmPeak: 12500 kB
VmSize: 12400 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 4800 kB
VmRSS: 4800 kB
Это полностью то, что вытащит ps. И полностью то, что вы будете извлекать в уроке 2 для своего mini-ps. Уже виден формат: key:\twhitespace\tvalue. Парсится в пять строк.
Если получилось — вы готовы. Идём строить ps.
Итог
Capstone — это не «много новой теории», а «применение всей теории». Три инструмента (ps, shell, monitor) покрывают центральные модули курса: процессы, память, IPC, file I/O, /proc. Каждый — компактный (~150-250 строк), реальный, запускаемый на любом Linux.
В уроке 2 — mini-ps. Читаем /proc/[pid]/*, парсим, форматируем колонками. После него команда ps -ef | head потеряет любую загадочность.