← Назад к вопросам

Как может возникнуть зомби-процесс

2.0 Middle🔥 141 комментариев
#Linux и администрирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Зомби-процесс: определение и механизм возникновения

Зомби-процесс (zombie process) — это процесс, который завершил своё выполнение, но его запись всё ещё находится в таблице процессов, потому что родительский процесс не прочитал его статус выхода.

Как возникает зомби-процесс

Механизм:

  1. Дочерний процесс завершает работу (вызывает exit() или завершается с ошибкой)
  2. Операционная система переводит процесс в состояние "завершён", но не удаляет его из таблицы процессов
  3. ОС отправляет сигнал SIGCHLD родительскому процессу
  4. Критический момент: Если родитель не обработает сигнал SIGCHLD и не вызовет wait() или waitpid(), дочерний процесс остаётся в таблице в виде зомби

Простой пример на bash:

# Запустим фоновый процесс
sleep 100 &
pid=$!

# Немедленно завершим его
kill $pid

# Процесс станет зомби, если родитель не вызовет wait()
ps aux | grep defunct  # увидим <defunct> статус

Пример на Python:

import subprocess
import time

# Создаём дочерний процесс
proc = subprocess.Popen(['sleep', '5'])

# Процесс завершится, но мы не вызовем wait()
time.sleep(10)

# В это время процесс будет зомби
# ps aux | grep sleep  -> увидим <defunct>

Когда возникают зомби

  • Завершение без обработки: Дочерний процесс завершился, но родитель не вызвал wait() или waitpid()
  • Плохая обработка сигналов: Родитель установил SIG_IGN для SIGCHLD или вообще не обрабатывает сигналы
  • Busy-loop: Родитель занят обработкой других задач и не проверяет статус дочерних процессов

Как исправить

Правильная обработка сигналов:

#!/bin/bash

# Функция для очистки зомби-процессов
cleanup() {
  while wait -n 2>/dev/null; do
    true
  done
}

trap cleanup SIGCHLD

# Теперь дочерние процессы будут корректно очищены
sleep 100 &
sleep 50 &

wait  # ждём все процессы

На Python:

import subprocess
import signal
import sys
import os

def sigchld_handler(signum, frame):
    while True:
        try:
            pid, status = os.waitpid(-1, os.WNOHANG)
            if pid == 0:
                break
        except ChildProcessError:
            break

signal.signal(signal.SIGCHLD, sigchld_handler)

proc = subprocess.Popen(['sleep', '100'])
# процесс будет правильно очищен

Мониторинг зомби-процессов

# Найти все зомби-процессы
ps aux | grep defunct

# Более подробно
ps -eo ppid,pid,cmd,stat | grep -i defunct

# Узнать родителя зомби
ps -o ppid= -p <zombie_pid>
Как может возникнуть зомби-процесс | PrepBro