Операционные системы

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

Карта раздела

  1. Процессы, потоки и goroutine — единицы изоляции и исполнения.
  2. Планирование CPU и переключение контекста — конкуренция за ядра и цена переключений.
  3. Виртуальная память: stack, heap и mmap — адресные пространства и отображения памяти.
  4. Paging, page fault и copy-on-write — страничная адресация и стоимость работы с памятью.
  5. Файловые дескрипторы и stdio — системные вызовы, буферизация и утечки FD.
  6. Сигналы Unix и жизненный цикл процесса — graceful shutdown и supervisor.
  7. IPC: pipe, socket и shared memory — обмен между процессами и границы изоляции.
  8. Syscall и граница user/kernel space — переход в ядро, контракты вызовов и их стоимость.

Зачем это на интервью

Вопросы по ОС проверяют не запоминание терминов, а способность объяснить поведение сервиса: почему добавление goroutine не ускорило CPU-bound работу, откуда взялся OOMKilled и как отличить блокировку I/O от дефицита CPU. Уверенный ответ связывает модель ОС с измерением и следующим действием.

Минимум для E4

  • Объяснять различие процесса, потока и goroutine, а также границу между рантаймом Go и ядром.
  • Понимать, что CPU, память, файловые дескрипторы и I/O имеют конечные лимиты.
  • Называть наблюдаемый симптом и подходящий инструмент Linux для базовой проверки.
  • Знать, что блокировки, сигналы и завершение процесса требуют явной обработки в сервисе.

Углубление для E5/Senior

  • Связывать p99 и throughput с очередями run queue, CPU throttling, page fault, контеншеном и переключениями контекста.
  • Выбирать лимиты контейнеров и параллелизм Go по измерениям, а не по числу логических CPU на машине.
  • Проектировать деградацию: backpressure, timeouts, ограничение конкуренции, корректный shutdown и диагностируемость инцидента.

Ключевые понятия

  • Kernel mode и user mode: привилегированный код ядра управляет аппаратурой; приложение запрашивает операции через системные вызовы.
  • Процесс: изолированное адресное пространство и набор ресурсов; поток — поток исполнения внутри процесса.
  • Планировщик выбирает исполняемый поток; виртуальная память даёт процессу собственное адресное пространство.
  • Файловый дескриптор — целочисленная ссылка процесса на открытый объект I/O; cgroup ограничивает или учитывает ресурсы группы процессов.

Типовые вопросы

  1. Почему goroutine не равна потоку ОС?
    • Goroutine планируется рантаймом Go на меньшем числе потоков ОС; поток нужен, когда выполнение должно попасть в ядро или реально занять CPU.
  2. Почему сервис может быть медленным при низком среднем CPU?
    • Причиной могут быть ожидание I/O, блокировки, CPU throttling, неравномерная нагрузка на ядра или page fault; нужны метрики и профилирование.
  3. Что проверите при ошибке «too many open files»?
    • Лимит RLIMIT_NOFILE, число и тип FD в /proc/<pid>/fd, места открытия без Close и пул соединений.
  4. Чем OOM killer отличается от ошибки выделения памяти в приложении?
    • OOM killer завершает процесс по решению ядра при нехватке памяти; ошибка выделения возникает в контексте процесса. В контейнере важны также лимиты cgroup.
  5. Зачем контейнеру cgroups, если есть namespaces?
    • Namespaces изолируют представление ресурсов, но не ограничивают их потребление; cgroups дают учёт и лимиты CPU, памяти и I/O.

Практика

  • Запустите CPU-bound и I/O-bound Go-примеры; сравните top, ps -L и профиль CPU из раздела Go.
  • Для тестового процесса снимите ulimit -n, ls /proc/<pid>/fd | wc -l и объясните разницу между лимитом и текущим использованием.
  • Создайте воспроизводимый graceful shutdown по сигналам Unix и проверьте, что новые запросы не принимаются, а текущие завершаются по deadline.

Частые ошибки и ловушки

  • Считать, что «одна goroutine = один поток» или что GOMAXPROCS создаёт ровно столько потоков ОС.
  • Делать вывод по средней загрузке CPU, игнорируя throttling, run queue и хвостовые задержки.
  • Путать видимость процесса в namespace с разрешением потреблять память или CPU.
  • Лечить симптом повышением лимита FD, не найдя утечку или неограниченный пул.

Связанные темы

База разработки и Computer Science · Процессы, потоки и goroutine · Go · Linux и сети · Наблюдаемость · System Design

Источники

  • Linux kernel documentation: The Linux Kernel API, cgroups v2 и документация подсистемы scheduler.
  • Michael Kerrisk, The Linux Programming Interface.
  • Документация Go: The Go Programming Language Specification и runtime package.
  • man 2 fork, man 2 clone, man 2 open, man 7 signal, man 7 cgroups.