# Процессы и сигналы

> Процесс — запущенная программа со своим PID, памятью и ресурсами; сигналы — асинхронные уведомления, которыми ядро и другие процессы сообщают процессу о событиях, например о просьбе завершиться.

Источник: https://llmdocs.ru/wiki/processes-signals/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Идентификатор**: PID; у родителя — PPID
- **Создание**: fork() и execve()
- **Первый процесс**: init/systemd (PID 1)
- **Состояния**: R (выполняется), S (спит), D (ожидает ввода-вывода), T (остановлен), Z (зомби)
- **Частые сигналы**: SIGTERM (15), SIGKILL (9), SIGINT (2), SIGHUP (1), SIGCHLD
- **Инструменты**: ps, top, htop, pgrep, kill, pkill, /proc
**Процесс** — экземпляр выполняющейся программы: код, загруженный в память, вместе с данными, открытыми файлами, переменными окружения и правами пользователя. У каждого процесса в [Linux](https://llmdocs.ru/wiki/linux.md) есть уникальный номер — **PID** — и родитель (PPID). **Сигнал** — короткое асинхронное уведомление, которое ядро или другой процесс посылает процессу: «завершись», «перечитай конфигурацию», «ты обратился к чужой памяти», «твой дочерний процесс закончил работу».

Понимание процессов и сигналов нужно, чтобы корректно останавливать службы, искать зависшие программы, писать скрипты и правильно завершать приложения в [Docker](https://llmdocs.ru/wiki/docker.md) и [Kubernetes](https://llmdocs.ru/wiki/kubernetes.md).

## Жизнь процесса

Новые процессы в Unix создаются двумя системными вызовами: **`fork()`** создаёт копию текущего процесса, а **`execve()`** заменяет программу в этой копии на другую.[2] Так оболочка запускает каждую команду: делает `fork`, в дочернем процессе вызывает `exec` нужной программы, а сама ждёт её завершения через `wait`.

Все процессы образуют дерево с корнем в процессе с PID 1 — сегодня это обычно [systemd](https://llmdocs.ru/wiki/systemd.md). Завершившись, процесс возвращает **код выхода** (0 — успех) и становится **зомби** — записью в таблице процессов, ожидающей, пока родитель прочитает код выхода. Если родитель умер раньше, «сирот» усыновляет PID 1 и сам их «хоронит».

| Состояние | Обозначение | Смысл |
|---|---|---|
| Выполняется | R | работает или готов к работе |
| Спит | S | ждёт события (сеть, таймер, ввод) |
| Непрерываемый сон | D | ждёт ввода-вывода, не реагирует даже на SIGKILL |
| Остановлен | T | приостановлен (Ctrl+Z, отладчик) |
| Зомби | Z | завершён, родитель не забрал код выхода |

## Просмотр процессов

```bash
ps aux                           # все процессы: пользователь, PID, CPU, память, команда
ps -ef --forest                  # дерево процессов
pgrep -a nginx                   # найти по имени
top                              # интерактивно; htop — удобнее
cat /proc/1234/status            # всё о процессе из виртуальной ФС /proc
ls -l /proc/1234/fd              # открытые файлы и сокеты
lsof -i :8080                    # какой процесс занял порт
```

Каталог `/proc` — окно в ядро: для каждого процесса есть каталог с его командной строкой, окружением, картой памяти и открытыми файлами.[3][4]

## Сигналы

| Сигнал | Номер | Действие по умолчанию | Когда приходит |
|---|---|---|---|
| SIGHUP | 1 | завершение | закрыт терминал; демоны часто перечитывают конфигурацию |
| SIGINT | 2 | завершение | Ctrl+C в терминале |
| SIGQUIT | 3 | завершение с дампом | Ctrl+\ |
| SIGKILL | 9 | немедленное завершение | `kill -9`; нельзя перехватить |
| SIGSEGV | 11 | завершение с дампом | обращение к недопустимой памяти |
| SIGPIPE | 13 | завершение | запись в закрытый канал |
| SIGTERM | 15 | завершение | вежливая просьба завершиться — `kill` по умолчанию |
| SIGCHLD | 17 | игнорируется | завершился дочерний процесс |
| SIGSTOP, SIGCONT | 19, 18 | остановка, продолжение | приостановить и возобновить; SIGSTOP нельзя перехватить |

Процесс может перехватить большинство сигналов и обработать их по-своему — например, по SIGTERM закрыть соединения и сохранить данные. SIGKILL и SIGSTOP перехватить нельзя: их обрабатывает ядро.[1]

```bash
kill 1234                        # SIGTERM — попросить завершиться
kill -HUP $(pgrep nginx)         # перечитать конфигурацию
kill -9 1234                     # SIGKILL — крайняя мера
pkill -f "python worker.py"      # по шаблону командной строки
```

## Корректное завершение

Правильный порядок остановки — сначала SIGTERM, дать процессу время закончить работу и только затем SIGKILL. Так поступают systemd (`TimeoutStopSec`), `docker stop` (по умолчанию 10 секунд)[5] и Kubernetes (`terminationGracePeriodSeconds`). Приложение должно обрабатывать SIGTERM: перестать принимать новые запросы, дождаться текущих, закрыть соединения с базой.

```python
import signal, sys

def shutdown(signum, frame):
    print("получен SIGTERM, завершаемся")
    server.stop(grace=10)
    sys.exit(0)

signal.signal(signal.SIGTERM, shutdown)
```

В [Bash](https://llmdocs.ru/wiki/shell-bash.md) обработчик ставится командой `trap 'cleanup' TERM INT EXIT`.

## Процессы в контейнерах

В контейнере приложение часто становится PID 1, а у PID 1 особые правила: ядро не применяет к нему действия сигналов по умолчанию, поэтому процесс, не установивший обработчик SIGTERM, просто его проигнорирует, и контейнер будет убит по таймауту. Кроме того, PID 1 обязан собирать зомби. Решения — запускать команду в exec-форме (`CMD ["python", "app.py"]`, а не через `sh -c`, см. [Dockerfile](https://llmdocs.ru/wiki/dockerfile.md)), обрабатывать сигналы в приложении или использовать маленький init вроде tini (`docker run --init`).[6]

## Приоритеты и ресурсы

Приоритет планирования задаётся значением **nice** от −20 (высший) до 19: `nice -n 10 ./backup.sh`, `renice`. Ограничения ресурсов — `ulimit` (число открытых файлов, размер стека) и cgroups (память, процессор; см. [Namespaces и cgroups](https://llmdocs.ru/wiki/namespaces-cgroups.md)). Когда память кончается, ядро запускает **OOM killer**, который завершает процесс с наибольшим «счётом» потребления — частая причина внезапной гибели баз данных и Java-приложений.

## См. также

- [systemd](https://llmdocs.ru/wiki/systemd.md)
- [Shell и Bash](https://llmdocs.ru/wiki/shell-bash.md)
- [Namespaces и cgroups](https://llmdocs.ru/wiki/namespaces-cgroups.md)
- [Конкурентность и параллелизм](https://llmdocs.ru/wiki/concurrency-parallelism.md)
- [Linux](https://llmdocs.ru/wiki/linux.md)

## Источники

1. [signal(7) — Linux manual page](https://man7.org/linux/man-pages/man7/signal.7.html)
2. [fork(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fork.2.html)
3. [proc(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc.5.html)
4. [ps(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ps.1.html)
5. [Docker Docs — docker container stop](https://docs.docker.com/reference/cli/docker/container/stop/)
6. [tini — A tiny but valid init for containers](https://github.com/krallin/tini)
