Какой статус должен получить процесс от родителя, чтобы он стал зомби (zombie)?

«Какой статус должен получить процесс от родителя, чтобы он стал зомби (zombie)?» — вопрос из категории Linux, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Процесс становится зомби (состояние Z в выводе ps или top), когда он завершил своё выполнение (exit), но его родительский процесс ещё не прочитал его статус завершения с помощью системного вызова wait() (или waitpid()).

Механика:

  1. Дочерний процесс завершается, отправляя родителю сигнал SIGCHLD.
  2. Операционная система сохраняет запись о процессе и его статусе завершения (код выхода, сигнал) в таблице процессов.
  3. Эта запись остаётся там до тех пор, пока родитель не вызовет wait(). Пока запись существует, процесс считается "зомби".
  4. После вызова wait() ОС удаляет запись о зомби-процессе.

Пример на bash, демонстрирующий появление зомби:

#!/bin/bash
# Запускаем дочерний процесс в фоне и сразу завершаем его
sleep 10 &
# Немедленно завершаем родительский скрипт, не дожидаясь дочернего процесса.
# В этот момент дочерний `sleep` ещё выполняется.
# Когда `sleep` завершится, его родителем станет процесс с PID 1 (init),
# который периодически вызывает wait() и очищает зомби.
# Но если бы родительский процесс остался жив и игнорировал SIGCHLD,
# дочерний процесс стал бы зомби.
exit 0

Влияние на систему и устранение:

  • Зомби-процессы не потребляют память (кроме небольшой записи в таблице процессов), но занимают PID.
  • Длительное существование множества зомби может исчерпать доступные PIDs.
  • Чтобы избежать зомби, родительский процесс должен:
    • Регулярно вызывать wait() для завершённых потомков.
    • Установить обработчик сигнала SIGCHLD с вызовом waitpid() с флагом WNOHANG для асинхронной очистки.
    • В крайнем случае — явно игнорировать сигнал SIGCHLD (signal(SIGCHLD, SIG_IGN)), что заставит ядро немедленно очищать дочерние процессы (но это не всегда переносимо).