← Linux: процессы вглубь
12 мин · средне · Урок 2 из 7

Состояния процесса: R, S, D, T, Z

Состояния процесса R/S/D/T/Z и где их смотреть.

Зачем процессу состояние

Ядро (kernel) держит все процессы в одной большой таблице. У каждой записи есть поле состояния. Оно говорит планировщику, что с процессом делать прямо сейчас: дать ему процессор, оставить спать или вообще не трогать.

Состояние процесса — это его текущий статус в таблице ядра. Значений немного, и почти все они помещаются в один буквенный код. Разберём пять основных: R, S, D, T, Z. Есть ещё X, но живой процесс в этом состоянии вы не поймаете.

R — работает или готов работать

R (running/runnable) значит одно из двух: процесс прямо сейчас крутится на ядре процессора либо стоит в очереди готовых и ждёт своей доли времени. Планировщик переключает такие процессы десятки раз в секунду, поэтому R вы чаще всего увидите у самой команды ps, которая как раз выполняется.

$ ps aux | grep -w R
deploy 1455  0.2  0.0  12100  3200 R+   10:14  0:00 ps aux

S — прерываемый сон

S (interruptible sleep) — процесс спит и ждёт события: пришедшего пакета, нажатия клавиши, ответа от другого процесса. Это нормальное состояние для большинства программ. Веб-сервер, который ждёт запрос, почти всё время висит в S и не тратит процессор.

$ ps aux
USER   PID %CPU %MEM    VSZ   RSS STAT START  TIME COMMAND
www    812  0.0  2.4 720160 98400 S    09:01  0:21 nginx: worker

Такой сон можно прервать сигналом. Придёт SIGTERM или нажатие клавиши, и процесс проснётся и обработает событие.

D — непрерываемый сон

D (uninterruptible sleep) — процесс ждёт завершения операции ввода-вывода, обычно с диска или по сети. Пока операция не закончится, ядро не отдаёт процессу управление и не доставляет ему сигналы.

Отсюда следствие, которое ломает многим картину мира: процесс в D не берёт даже kill -9. SIGKILL встанет в очередь и сработает только когда диск ответит и процесс выйдет из D.

$ ps aux | grep -w D
root  9021  0.0  0.1      0     0 D    11:02  0:00 [kworker/u8:2-writeback]

Короткий D — обычное дело при активном чтении с диска. Процесс, застрявший в D надолго, обычно означает больной диск или зависшую сетевую файловую систему (NFS).

T — остановлен

T (stopped) — процесс поставлен на паузу и не выполняется. Так бывает после Ctrl+Z в терминале или после сигнала SIGSTOP. Процесс никуда не делся, он просто заморожен и ждёт команды продолжить.

$ sleep 300
^Z
[1]+  Stopped   sleep 300
$ ps aux | grep sleep
user  2043  0.0  0.0   8300   900 T    11:10  0:00 sleep 300

Разбудить его можно сигналом SIGCONT (fg, bg или kill -CONT). Пара SIGSTOP/SIGCONT — единственный штатный способ поставить процесс на паузу и снять её.

Z — зомби

Z (zombie) — процесс уже завершился, но его код возврата ещё не забрал родитель вызовом wait(). Такая запись держит только номер PID в таблице процессов, память и файлы уже освобождены.

$ ps aux | grep defunct
user  3301  0.0  0.0      0     0 Z    11:15  0:00 [worker] <defunct>

Зомби разбираем отдельным уроком. Пока запомните: Z не ест ресурсов, он занимает лишь строку в таблице.

Где смотреть состояние

Первый источник — колонка STAT в ps aux. К основной букве иногда добавляются модификаторы: s (лидер сессии), l (многопоточный), + (в foreground-группе терминала), < (высокий приоритет).

$ ps aux
USER   PID %CPU %MEM    VSZ   RSS STAT START  TIME COMMAND
root     1  0.0  0.1 168240 11500 Ss   09:00  0:02 /sbin/init
www    812  1.3  2.4 720160 98400 Sl   09:01  0:21 nginx: worker
deploy 1455  0.0  0.0  12100  3200 R+   10:14  0:00 ps aux

Второй источник — файл /proc/<PID>/status, там состояние написано словом:

$ grep State /proc/812/status
State:  S (sleeping)

Сводка состояний

КодСостояниеРеагирует на сигналы
Rвыполняется или готовода
Sпрерываемый сонда
Dнепрерываемый сон (I/O)нет, пока не закончит I/O
Tостановленждёт SIGCONT
Zзомбиуже мёртв

Две ловушки

Первая: «процесс либо работает, либо мёртв». Между R и завершением есть сон (S, D) и пауза (T). Программа в S — здоровая программа, а не зависшая.

Вторая: «процесс в D можно снять через kill -9». Нельзя. SIGKILL подождёт, пока диск ответит:

$ kill -9 9021
$ ps aux | grep 9021        # всё ещё D, kill в очереди
root  9021  0.0  0.1      0     0 D    11:02  0:00 [kworker/u8:2-writeback]

Про сигналы, которые всплывут дальше

Состояния тесно связаны с сигналами, поэтому зафиксируем несколько фактов заранее.

SIGKILL (9) и SIGSTOP (19) — единственные два сигнала, которые нельзя перехватить, заблокировать или проигнорировать. Остальные процесс может обработать по-своему.

У каждого сигнала есть действие по умолчанию, всего их пять: Term (завершить), Ign (проигнорировать), Core (завершить и сбросить дамп), Stop (остановить), Cont (продолжить).

Отдельно стоит SIGCHLD: его ядро шлёт родителю, когда потомок завершился. По умолчанию SIGCHLD игнорируется, поэтому родитель обязан сам вызвать wait(), чтобы убрать зомби.

Если родитель умрёт раньше потомка, потомок становится осиротевшим. Его усыновляет init (PID 1), который регулярно делает wait() и подчищает завершившихся. С ядра 3.4 роль такого сборщика можно передать специально назначенному процессу-subreaper, а не только PID 1.

Что важно запомнить

R — работает или готово работать, S — здоровый сон в ожидании события.

D — ждёт ввод-вывод и не берёт даже kill -9, пока диск не ответит.

T — пауза, снимается SIGCONT; Z — завершился, ждёт wait() родителя.

Состояние видно в колонке STAT (ps aux) и в /proc/<PID>/status.

SIGKILL и SIGSTOP нельзя перехватить или заблокировать. Держите это в голове.

В следующем уроке — сигналы вглубь: какие из них можно перехватить, а какие нет.

Дрилл · вопросы как на собесе

Проверь себя без подсказок

Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.

01

Какие состояния процесса бывают в Linux?

LIN-013

Прошли материал до конца? Отметьте урок пройденным.