Процесс, его контекст и состояния
Программа и процесс
Программа — файл на диске: машинный код и данные. Процесс — программа в момент выполнения вместе со всем, что ей нужно: адресное пространство, значения регистров, открытые файлы, состояние.
Одну программу могут выполнять несколько процессов одновременно (десять терминалов с bash — десять процессов одной программы).
Процесс — единица, которой ОС выделяет ресурсы: память, файлы, процессорное время. Ядро описывает каждый процесс структурой-дескриптором (PCB, Process Control Block), в Linux это struct task_struct.
Контекст процесса
Всё, что нужно, чтобы остановить процесс и потом продолжить с того же места:
| Часть | Что входит |
|---|---|
| Пользовательский контекст | код, данные, стек, куча, разделяемые библиотеки — содержимое адресного пространства |
| Регистровый контекст | счётчик команд, указатель стека, регистры общего назначения, флаги |
| Системный контекст | то, что ядро хранит о процессе: PID, PPID, UID, состояние, приоритет, таблицы страниц, таблица файловых дескрипторов, обработчики и маски сигналов, текущий каталог, лимиты, стек ядра |
При переключении процессов ядро сохраняет регистровый контекст в системной части, а пользовательский остаётся в памяти (меняется лишь cr3 — какой адресное пространство видит процессор).
task_struct (упрощённо)
struct task_struct {
volatile long state; /* TASK_RUNNING, TASK_INTERRUPTIBLE, ... */
pid_t pid; /* идентификатор потока */
pid_t tgid; /* идентификатор группы потоков = PID процесса */
struct task_struct *real_parent;/* родитель */
struct list_head children; /* список потомков */
struct mm_struct *mm; /* адресное пространство: VMA, таблицы страниц (pgd) */
struct files_struct *files; /* таблица открытых файлов */
struct fs_struct *fs; /* корень и текущий каталог */
struct signal_struct *signal; /* общие сигнальные данные, сеанс, группа */
struct sighand_struct*sighand; /* обработчики сигналов */
sigset_t blocked; /* маска блокированных сигналов */
struct sigpending pending; /* ожидающие сигналы */
const struct cred *cred; /* uid, gid, права */
int prio; /* приоритет */
/* ... ещё сотни полей ... */
};
Идентификаторы
#include <unistd.h>
pid_t me = getpid(); /* свой PID */
pid_t parent = getppid(); /* PID родителя */
Каждый процесс (кроме самых первых, созданных ядром) имеет родителя. Процессы образуют дерево, корень пространства пользователя — init (PID 1).
ps -eo pid,ppid,stat,comm | head
pstree -p
Состояния процесса
| Состояние | В Linux | В ps |
|---|---|---|
| Выполняется / готов | TASK_RUNNING |
R |
| Ожидает (прерываемо сигналом) | TASK_INTERRUPTIBLE |
S |
| Ожидает (непрерываемо, обычно диск) | TASK_UNINTERRUPTIBLE |
D |
| Остановлен | TASK_STOPPED |
T |
| Зомби | EXIT_ZOMBIE |
Z |
Обратите внимание
Из ожидания процесс никогда не переходит сразу к выполнению: сначала становится готовым и ждёт, пока планировщик выберет его. Linux не различает «готов» и «выполняется» в поле состояния — оба TASK_RUNNING.
Остановленное состояние и сигналы
Состояние «остановлен» связано с сигналами: SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU по умолчанию останавливают процесс (не завершая его), а SIGCONT продолжает. Это столбец «останавливает процесс» в таблице задачи 1.
Итог
- Процесс — выполняющийся экземпляр программы; ядро описывает его дескриптором (
task_struct). - Контекст: пользовательский (память), регистровый, системный (данные ядра о процессе).
- Состояния: готов, выполняется, ожидает, остановлен, зомби.
- Процессы образуют дерево с корнем init (PID 1).
Практика решено 0 из 5
Чем процесс отличается от программы?
Отнесите элементы к частям контекста процесса.
| Пользовательский контекст | Регистровый контекст | Системный контекст (в ядре) | |
|---|---|---|---|
| Код и данные программы, стек, куча | |||
| Счётчик команд (rip) и указатель стека | |||
| Таблица открытых файловых дескрипторов | |||
| Обработчики сигналов и маска сигналов | |||
| Таблицы страниц процесса | |||
| Регистры общего назначения (rax, rbx...) | |||
| PID, PPID, идентификаторы пользователя |
Процесс читает с клавиатуры. Расставьте его состояния по порядку:
-
Выполняется (running): вызывает
read(0, ...) -
Выполняется (running): планировщик выбрал процесс,
readвозвращает данные - Ожидает (sleeping): данных нет, ядро усыпляет процесс до нажатия клавиши
- Готов (ready/runnable): пришло прерывание клавиатуры, ядро разбудило процесс и поставило в очередь
Как в выводе ps обозначается состояние процесса-зомби? (одна буква)
Какие переходы между состояниями возможны?
Войдите, чтобы отмечать пройденные уроки.