ОП.05Процессы: PID, состояния и сигналызанятие 7Материалы

Часть 3 из 7

Состояния процесса

В этой части разберём, в каких состояниях бывает процесс, как их читать в столбце STAT команды ps и как получить каждое состояние на опыте.

  1. 3.1 Пять состояний
  2. 3.2 Состояния на опыте

3.1 Пять состояний

Процессор в каждый момент выполняет на одном ядре только один процесс. Остальные либо ждут своей очереди, либо ждут события — нажатия клавиши, ответа диска, истечения таймера. Поэтому большую часть времени почти все процессы системы «спят». Ядро хранит для каждого процесса его состояние, а ps показывает его в столбце STAT одной буквой.

БукваСостояниеЧто происходитПример
Rrunning — выполняетсяпроцесс работает на процессоре или стоит в очереди к немуyes > /dev/null — бесконечный вывод
Ssleeping — спитждёт события и проснётся, когда оно наступит или придёт сигналsleep 500, оболочка в ожидании ввода
Duninterruptible — ждёт устройствождёт завершения ввода-вывода, сигналы до его конца не обрабатываетчтение с медленного или зависшего диска
Tstopped — остановленприостановлен сигналом и ждёт команды продолжитьпроцесс после Ctrl+Z
Zzombie — зомбиуже завершился, но родитель ещё не забрал код завершенияпотомок, родитель которого не вызывает wait

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

Иногда после буквы состояния стоят дополнительные знаки: s — у оболочки терминала, + — у процесса, который сейчас занимает терминал. Для состояния важна только первая буква. Буквой I помечены служебные потоки ядра, их в системе много.

3.2 Состояния на опыте

В опыте получим четыре состояния. yes > /dev/null бесконечно печатает строку y в устройство, которое всё выбрасывает, — процесс всё время занят и находится в состоянии R. sleep 500 спит. Команда sleep 600 без & занимает терминал, а сочетание Ctrl+Z останавливает её — состояние T.

Зомби получается, когда потомок завершился, а родитель не забрал его код завершения. В опыте bash -c 'sleep 1 & exec sleep 300' оболочка запускает sleep 1 в фон, а затем заменяет себя программой sleep 300. Через секунду потомок sleep 1 завершается, но его родитель теперь — sleep 300, который не умеет ждать потомков. Потомок остаётся зомби с пометкой <defunct>.

Последняя команда считает процессы системы по состояниям: ps -eo stat= выводит столбец STAT всех процессов без заголовка, cut -c1 оставляет первую букву, sort и uniq -c считают одинаковые буквы.

В терминалеЧетыре состояния
  1. yes > /dev/null &# всё время занят
    что делает

    Что делает команда. Запускает в фоне процесс, который бесконечно пишет строку y в устройство-«корзину»; он всё время занят.

    По частям:

    yes
    бесконечно печатать строку y
    >
    записать вывод в файл
    /dev/null
    устройство, которое выбрасывает всё записанное
    &
    запустить команду слева в фоне и сразу продолжить
  2. sleep 500 &# спит
    что делает

    Что делает команда. Запускает в фоне процесс, который спит 500 секунд.

    По частям:

    sleep
    ничего не делать указанное число секунд
    500
    сколько секунд
    &
    запустить команду слева в фоне и сразу продолжить
  3. bash -c 'sleep 1 & exec sleep 300' &# будущий зомби
    что делает

    Что делает команда. Запускает оболочку, которая порождает потомка и заменяет себя программой sleep; через секунду потомок станет зомби.

    По частям:

    bash -c '…'
    запустить bash и выполнить команды из строки
    sleep 1 &
    потомок: спит секунду в фоне и завершается
    exec sleep 300
    заменить саму оболочку программой sleep 300; новая программа не ждёт потомков
    &
    запустить всё в фоне
  4. sleep 2# дать потомку завершиться
    что делает

    Что делает команда. Ждёт две секунды, чтобы потомок успел завершиться.

    По частям:

    sleep
    ничего не делать указанное число секунд
    2
    сколько секунд
  5. sleep 600# без & — занимает терминал
    что делает

    Что делает команда. Запускает sleep на переднем плане: терминал занят, пока его не остановить.

    По частям:

    sleep
    ничего не делать указанное число секунд
    600
    сколько секунд
  6. ^Z# Ctrl+Z: остановить
  7. ps -o pid,ppid,stat,cmd# состояния процессов терминала
    что делает

    Что делает команда. Выводит процессы текущего терминала: номер, родителя, состояние и команду.

    По частям:

    ps
    вывести сведения о процессах
    -o pid,ppid,stat,cmd
    выводить столбцы pid,ppid,stat,cmd
  8. ps -eo stat= | cut -c1 | sort | uniq -c# сколько процессов в каждом состоянии
    что делает

    Что делает команда. Считает все процессы системы по первой букве состояния.

    По частям:

    ps
    вывести сведения о процессах
    -eo stat=
    -e — все процессы системы; -o stat= — выводить только этот столбец, знак = убирает заголовок
    |
    передать вывод левой команды на вход следующей
    cut
    вырезать из строк нужные символы или поля
    -c1
    оставить первый символ строки
    |
    передать вывод левой команды на вход следующей
    sort
    отсортировать строки
    |
    передать вывод левой команды на вход следующей
    uniq
    объединить одинаковые соседние строки
    -c
    перед каждой строкой вывести, сколько раз она повторилась
Результат

в столбце STAT видны R у yes, S у sleep, T у остановленного sleep 600 и Z у потомка с пометкой <defunct>; в системе спят почти все процессы.

Снимок 3.1Ubuntu 24.04
  1. 1Ctrl+Z остановил задание
  2. 2R: yes занят всё время
  3. 3S: sleep ждёт таймер
  4. 4Z: потомок завершился, родитель не забрал код
  5. 5T: остановлен
  6. 6в системе спят почти все процессы
Процессы терминала в состояниях R, S, T и Z; число процессов системы по состояниям.Весь снимок ↗

Процессы терминала в состояниях R, S, T и Z; число процессов системы по состояниям.

Что показывает снимок. В таблице процессов терминала видны все четыре состояния: R у yes, S у sleep, T у остановленного sleep 600 и Z у потомка с пометкой <defunct>; в системе 160 процессов спят.

Где это пригодится. Если сервер тормозит, сначала смотрят процессы в состоянии R и D: первые занимают процессор, вторые ждут медленный диск.

На схеме ниже показаны переходы между состояниями и события, которые их вызывают. Нажмите на состояние, чтобы увидеть, как процесс в него попадает и как из него выходит.

Схема · переходы между состояниями
forkждётсобытиеввод-выводготовоSTOPCONTexitwait•созданиеRвыполняетсяSспитDждёт устройствоTостановленZзомби•удалён

Итоги части 3

  • Столбец STAT в ps: R — выполняется, S — спит, D — ждёт устройство, T — остановлен, Z — зомби.
  • Почти все процессы системы большую часть времени спят и процессор не занимают.
  • Ctrl+Z останавливает процесс переднего плана — состояние T.
  • Зомби — завершившийся процесс, код завершения которого родитель ещё не забрал.

В отчётСнимок с четырьмя состояниями и объяснение, почему потомок стал зомби.

Открыть в отдельной вкладке ↗