Иное название для процесса — задание или задача (task). О процессах в ядре операционной системы Linux говорят как о задачах. В этой книге оба понятия взаимозаменяемы, хотя по возможности для представления работающей программы в ядре будет использоваться термин задача , а для представления в режиме пользователя — термин процесс .
Дескриптор процесса и структура task structure
Ядро хранит информацию о всех процессах в двухсвязном списке, который называется task list [10] Иногда в литературе по построению операционных систем этот список называется task array (массив задач). Поскольку в ядре Linux используется связанный список, а не статический массив, его называют task list .
( список задач ). Каждый элемент этого списка является дескриптором процесса и имеет тип структуры struct task_struct
, которая описана в файле include/linux/sched.h
. Дескриптор процесса содержит всю информацию об определенном процессе.
Структура task_struct
— достаточно большая структура данных размером порядка 1,7 Кбайт на 32-разрядной машине. Однако этот размер не такой уж большой, учитывая, что в данной структуре содержится вся информация о процессе, которая необходима ядру. Дескриптор процесса содержит данные, которые описывают выполняющуюся программу, — открытые файлы, адресное пространство процесса, ожидающие на обработку сигналы, состояние процесса и многое другое (рис. 3.1).
Рис. 3.1. Дескриптор процесса и список задач
Выделение дескриптора процесса
Память для структуры task_struct
выделяется с помощью подсистемы выделения памяти, которая называется слябовый распределитель ( slab allocator ), для возможности повторного использования объектов и раскрашивания кэша (cache coloring) (см. главу 11, "Управление памятью"). В ядрах до серии 2.6 структура task_struct
хранилась в конце стека ядра каждого процесса. Это позволяет для аппаратных платформ, у которых достаточно мало регистров процессора (как, например, платформа x86), вычислять местоположение дескриптора процесса, только зная значение регистра указателя стека ( stack pointer ), без использования дополнительных регистров для хранения самого адреса этого местоположения. Так как теперь дескриптор процесса создается с помощью слябового распределителя, была введена новая структура thread_info
, которая хранится в области дна стека (для платформ, у которых стек растет в сторону уменьшения значения адреса памяти) или в области вершины стека (для платформ, у которых стек растет в сторону увеличения значения адреса памяти) [11] Причиной создания структуры thread_info было не только наличие аппаратных платформ, обедненных регистрами процессора, но и то, что положение этой структуры позволяет достаточно просто рассчитывать смешения адресов для значений ее полей при использовании языка ассемблера.
(рис. 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
этой задачи.
Хранение дескриптора процесса
Система идентифицирует процессы с помощью уникального значения, которое называется идентификатором процесса ( process identification , PID ). Идентификатор PID
— это целое число, представленное с помощью скрытого типа pid_t
[12] Скрытый тип (opaque type) — это тип данных, физическое представление которого неизвестно или не существенно.
, который обычно соответствует знаковому целому— int
.
Однако, для обратной совместимости со старыми версиями ОС Unix и Linux максимальное значение этого параметра по умолчанию составляет всего лишь 32768 (что соответствует типу данных short int
). Ядро хранит значение данного параметра в поле pid
дескриптора процесса.
Читать дальше