Внутренности ОС и процессы
Внутренности операционной системы для Go-бэкенд-инженеров — виртуальная память, системные вызовы, процессы, файловые дескрипторы, сигналы, OOM killer и загрузка CPU.
9 вопросов
JuniorТеорияЧастоЧем процесс ОС отличается от системного потока (thread)?
Чем процесс ОС отличается от системного потока (thread)?
Потоки внутри одного процесса делят общее адресное пространство; разные процессы по умолчанию память не делят. В ядре Linux и то, и другое — один примитив Task, различающийся в основном тем, что разделяется. Процессы всё же могут обмениваться данными через сокеты, пайпы или сигналы либо явно делить память через shm_open или mmap.
Типичные ошибки
- ✗Переворачивать — утверждать, что процессы делят память, а потоки нет
- ✗Не знать, что оба — это Task в ядре Linux
- ✗Забывать, что процессы могут делить память через
shm_openилиmmap
Уточняющие вопросы
- →Как горутина соотносится с OS-потоком в этой картине?
- →Какими основными способами два процесса общаются?
JuniorТеорияИногдаtop показывает процесс на 146% CPU. Это реально и стоит ли беспокоиться?
top показывает процесс на 146% CPU. Это реально и стоит ли беспокоиться?
Да, это реально. top показывает CPU процесса как сумму по всем ядрам, поэтому 146% означает, что процесс использует примерно 1.46 ядра одновременно — это нормально для многопоточной программы на многоядерной машине. Без дополнительного контекста нельзя сказать, что это проблема; в общем случае всё в порядке. Считать любое значение выше 100% невозможным — это ответ-красный-флаг.
Типичные ошибки
- ✗Считать, что CPU процесса не может превышать 100%
- ✗Полагать, что любое показание выше 100% — сбой, требующий действий
- ✗Путать процент, суммированный по ядрам, с давлением свопа или памяти
Уточняющие вопросы
- →Как планировщик Completely Fair Scheduler в Linux делит время CPU между задачами?
- →Что значит 146% CPU для процесса внутри квоты cgroup на 1 ядро?
JuniorТеорияИногдаЧто такое файловый дескриптор и что означают дескрипторы 0, 1 и 2?
Что такое файловый дескриптор и что означают дескрипторы 0, 1 и 2?
Файловый дескриптор — это небольшое целое число, которое ОС возвращает при открытии ресурса, и которое затем используется для чтения, записи и других операций. Он обозначает не только файлы на диске, но и пайпы, сокеты, устройства и отображённые в память файлы. По соглашению 0 — это stdin, 1 — stdout, 2 — stderr; каждый процесс стартует с этими тремя открытыми.
Типичные ошибки
- ✗Считать, что дескрипторы применимы только к обычным файлам на диске
- ✗Нумеровать стандартные потоки неверно вместо 0/1/2
- ✗Путать целое-дескриптор с путём или содержимым файла
Уточняющие вопросы
- →Почему
dfможет показывать свободное место, а запись падает сno space left? - →Почему удаление открытого файла не освобождает место на диске сразу?
JuniorТеорияИногдаКак убить процесс в Linux и почему kill -9 — плохой первый выбор?
Как убить процесс в Linux и почему kill -9 — плохой первый выбор?
Найдите PID через ps aux | grep или top, затем пошлите сигнал командой kill <pid>. Обычный kill шлёт SIGTERM (15), прося процесс завершиться корректно и освободить ресурсы. kill -9 шлёт SIGKILL, который процесс не может перехватить или обработать — он гибнет мгновенно без очистки, поэтому его применяют, только когда SIGTERM игнорируется.
Типичные ошибки
- ✗Тянуться к
-9до попытки корректного SIGTERM - ✗Думать, что SIGKILL можно перехватить и обработать в процессе
- ✗Не знать, как найти PID перед отправкой сигнала
Уточняющие вопросы
- →Почему Go-сервису стоит перехватывать SIGTERM для graceful shutdown?
- →Что происходит с открытыми дескрипторами процесса после SIGKILL?
JuniorТеорияИногдаВ чём разница между user space и kernel space и зачем нужно такое разделение?
В чём разница между user space и kernel space и зачем нужно такое разделение?
Прикладной код работает в user space — ограниченном режиме процессора, где видна только собственная виртуальная память процесса и недоступны привилегированные инструкции. Ядро работает в kernel space с полным доступом к устройствам, управлению памятью и всему набору инструкций. Разделение изолирует ОС, чтобы сбойное или вредоносное приложение не повредило систему; переход выполняется через системный вызов.
Типичные ошибки
- ✗Считать, что разделение — про области RAM, а не про режимы привилегий процессора
- ✗Думать, что приложение входит в kernel space без системного вызова или прерывания
- ✗Путать уровень привилегий с расположением на диске и в памяти
Уточняющие вопросы
- →Какой механизм процессора фактически выполняет переход в kernel space?
- →Почему переход из user в kernel space относительно дорогой?
JuniorТеорияИногдаЧто такое страница памяти в системе виртуальной памяти?
Что такое страница памяти в системе виртуальной памяти?
Страница — это единица фиксированного размера (обычно 4 КБ), которой ОС управляет виртуальной памятью. Ядро отображает каждую виртуальную страницу на физический фрейм, на файл или на своп, а биты прав на страницу защищают области от записи или исполнения. Страничная организация даёт процессам безопасно делить физическую RAM и каждому — своё изолированное адресное пространство.
Типичные ошибки
- ✗Путать страницу с целым сегментом или образом всего процесса
- ✗Забывать, что страницы могут отображаться на файл или своп, а не только на физическую RAM
- ✗Упускать биты прав на страницу, обеспечивающие защиту
Уточняющие вопросы
- →Если каждое обращение к памяти требует трансляции виртуального адреса в физический, как структурирующий кэш
TLBдержит это быстрым? - →Что такое hugepages и каким нагрузкам они выгодны?
MiddleТеорияИногдаСервис с утечкой памяти работает на голом сервере. Что произойдёт, когда память закончится?
Сервис с утечкой памяти работает на голом сервере. Что произойдёт, когда память закончится?
Зависит от свопа. Если своп включён, система может долго тянуть, выгружая память на диск. Если своп выключен, OOM killer ядра начинает убивать процессы, чтобы освободить память, — и не обязательно ваш. OOM killer решает по резидентной памяти (RSS, то, что реально отображено в физическую RAM), а не по большему виртуальному размеру.
Типичные ошибки
- ✗Думать, что убивают всегда именно текущий процесс с утечкой
- ✗Считать, что OOM killer решает по виртуальному размеру, а не по RSS
- ✗Игнорировать, что своп может надолго отсрочить OOM
Уточняющие вопросы
- →Почему ядро выбирает жертву по RSS, а не по виртуальному размеру?
- →Как лимит памяти cgroup меняет это поведение внутри контейнера?
MiddleТеорияИногдаЧто такое системный вызов (syscall) и что происходит с процессором при его выполнении?
Что такое системный вызов (syscall) и что происходит с процессором при его выполнении?
Системный вызов — это запрос программы к ОС на операцию, которую она не может сделать сама: чтение файла, открытие сокета, fork. Вызов переводит процессор из user mode в kernel mode: сохраняется состояние пользователя, происходит переход в привилегированный контекст ядра, отрабатывает обработчик, затем возврат. Например, fork клонирует процесс, а epoll позволяет одной горутине ждать готовности многих дескрипторов к чтению.
Типичные ошибки
- ✗Считать syscall обычной библиотечной функцией без смены режима
- ✗Забывать, что переход user→kernel сохраняет и восстанавливает состояние процессора
- ✗Думать, что
forkиepoll— фичи языка, а не системные вызовы ОС
Уточняющие вопросы
- →Почему блокирующий syscall может занять целый OS-поток в Go-программе?
- →Чем
epollотличается отselectпри наблюдении за многими дескрипторами?
SeniorТеорияИногдаКакие примитивы синхронизации предлагает операционная система, и чем они различаются?
Какие примитивы синхронизации предлагает операционная система, и чем они различаются?
Mutex даёт эксклюзивный доступ и блокирует ждущих (ОС снимает их с выполнения). Semaphore допускает до N владельцев, обобщая mutex. Spinlock крутится в ожидании без сна — выгоден лишь для очень коротких критических секций на нескольких ядрах. Advisory-блокировки файлов (flock) координируют процессы. В Linux futex — быстрый userspace-примитив, на котором большинство из них построено.
Типичные ошибки
- ✗Смешивать mutex и semaphore, не видя в mutex частный случай
N=1 - ✗Думать, что spinlock всегда быстрее, игнорируя, что он тратит CPU в ожидании
- ✗Не знать, что userspace-mutex в Linux построены на ядерном
futex
Уточняющие вопросы
- →Почему spinlock — плохой выбор на одноядерной машине?
- →Как
futexизбегает захода в ядро на быстром пути без конкуренции?