Выход из программы осуществляется с помощью системного вызова exit(). Эта функция завершает процесс и освобождает все занятые им ресурсы. Родительский процесс может запросить о состоянии порожденных им процессов с помощью системного вызова wait4()[9], который заставляет один процесс ожидать завершения другого. Когда процесс завершается, он переходит в специальное состояние wait() или waitpid().
Иное название для процесса —
Дескриптор процесса и структура task structure
Ядро хранит информацию о всех процессах в двухсвязном списке, который называется struct task_struct, которая описана в файле include/linux/sched.h. Дескриптор процесса содержит всю информацию об определенном процессе.
Структура task_struct — достаточно большая структура данных размером порядка 1,7 Кбайт на 32-разрядной машине. Однако этот размер не такой уж большой, учитывая, что в данной структуре содержится вся информация о процессе, которая необходима ядру. Дескриптор процесса содержит данные, которые описывают выполняющуюся программу, — открытые файлы, адресное пространство процесса, ожидающие на обработку сигналы, состояние процесса и многое другое (рис. 3.1).
Рис. 3.1. Дескриптор процесса и список задач
Выделение дескриптора процесса
Память для структуры task_struct выделяется с помощью подсистемы выделения памяти, которая называется task_struct хранилась в конце стека ядра каждого процесса. Это позволяет для аппаратных платформ, у которых достаточно мало регистров процессора (как, например, платформа x86), вычислять местоположение дескриптора процесса, только зная значение регистра thread_info, которая хранится в области дна стека (для платформ, у которых стек растет в сторону уменьшения значения адреса памяти) или в области вершины стека (для платформ, у которых стек растет в сторону увеличения значения адреса памяти)[11] (рис. 3.2.).
Рис 3.2. Дескриптор процесса и стек ядра
Структура struct thread_info для платформы x86 определена в файле в следующем виде.
struct thread_info {
struct task_struct *task;
struct exec_domain *exec_domain;
unsigned long flags;
unsigned long status;
__u32 cpu;
__s32 preempt_count;
mm_segment_t addr_limit;
struct restart_block restart_block;
unsigned long previous_esp;
__u8 supervisor_stack[0];
};
Для каждой задачи ее структура thread_info хранится в конце стека ядра этой задачи. Элемент структуры thread_info с именем task является указателем на структуру task_struct этой задачи.
Хранение дескриптора процесса
Система идентифицирует процессы с помощью уникального значения, которое называется PID — это целое число, представленное с помощью скрытого типа pid_t[12] , который обычно соответствует знаковому целому— int.
Однако, для обратной совместимости со старыми версиями ОС Unix и Linux максимальное значение этого параметра по умолчанию составляет всего лишь 32768 (что соответствует типу данных short int). Ядро хранит значение данного параметра в поле pid дескриптора процесса.