Введение

Компьютерный экземпляр программного обеспечения, создавший один или несколько дочерних процессов.

В информатике родительский процесс — это процесс, который создал один или несколько дочерних процессов.

Системы типа Unix

В операционных системах, подобных Unix, каждый процесс, за исключением процесса запуска Linux (сваппера), создается, когда другой процесс выполняет системный вызов fork. Процесс, вызвавший fork, является родительским, а вновь созданный процесс – дочерним. Каждый процесс (кроме процесса 0) имеет один родительский процесс, но может иметь множество дочерних процессов. Ядро операционной системы идентифицирует каждый процесс по его идентификатору процесса. Процесс 0 – это специальный процесс, который создается при загрузке системы; после создания дочернего процесса (процесс 1), процесс 0 становится процессом-сваппером (иногда также известным как "бездействующая задача"). Процесс 1, известный как init, является предком всех остальных процессов в системе.

Линукс

В ядре Linux, где различие между процессами и POSIX-потоками весьма незначительно, существует два типа родительских процессов: фактический родитель и родительский процесс. Родительский процесс – это процесс, получающий сигнал SIGCHLD при завершении дочернего процесса, а фактический родитель – это поток, который фактически создал этот дочерний процесс в многопоточной среде. Для обычного процесса оба этих значения совпадают, но для POSIX-потока, выступающего в роли процесса, они могут различаться.

Процессы зомби

Операционная система поддерживает таблицу, которая связывает каждый процесс, посредством его идентификатора процесса (обычно называемого "pid"), с данными, необходимыми для его функционирования. В течение времени жизни процесса эти данные могут включать сегменты памяти, выделенные процессу, аргументы, с которыми он был вызван, переменные окружения, счетчики использования ресурсов, идентификатор пользователя, идентификатор группы и набор групп, а также, возможно, другие типы информации. Когда процесс завершает свое выполнение, либо путем вызова exit (даже неявно, выполняя команду return из основной функции), либо путем получения сигнала, вызывающего его принудительное завершение, операционная система освобождает большую часть ресурсов и информации, связанных с этим процессом, но сохраняет данные об использовании ресурсов и код завершения, поскольку родительский процесс может быть заинтересован в том, успешно ли завершился дочерний процесс (используя стандартные функции для декодирования кода завершения) и сколько системных ресурсов он потреблял во время выполнения. По умолчанию система предполагает, что родительский процесс действительно заинтересован в этой информации в момент завершения дочернего процесса, и поэтому отправляет родителю сигнал SIGCHLD, чтобы уведомить о наличии данных о дочернем процессе, которые необходимо собрать. Сбор этих данных осуществляется путем вызова функции семейства wait (самой wait или одной из ее разновидностей, таких как waitpid, waitid или wait4). Как только сбор выполнен, система освобождает последние фрагменты информации о дочернем процессе и удаляет его pid из таблицы процессов. Однако, если родительский процесс задерживается со сбором данных дочернего процесса (или не выполняет его вообще), система не имеет другого выбора, кроме как хранить pid и данные о завершении дочернего процесса в таблице процессов неопределенно долго. Такой завершенный процесс, данные которого не были собраны, называется процессом-зомби или просто зомби в терминологии UNIX. Название является юмористической аналогией, основанной на том, что завершенный процесс считается "больше не живым" или "мертвым", поскольку он фактически прекратил функционировать, а задерживающийся мертвый процесс все еще "существует" в "мире живых" процессов – таблице процессов, – который, следовательно, фактически является "немертвым" или "зомби". Процессы-зомби могут создавать проблемы в системах с ограниченными ресурсами или с ограниченным размером таблицы процессов, поскольку создание новых активных процессов может быть заблокировано из-за ресурсов, которые все еще используются долгоживущими зомби. Поэтому в любой программе, которая может порождать дочерние процессы, хорошей практикой программирования является наличие кода, предотвращающего образование долгоживущих зомби из ее дочерних процессов. Наиболее очевидный подход – это код, который вызывает wait или одну из ее разновидностей после создания нового процесса. Если программа должна создавать много дочерних процессов, которые могут выполняться асинхронно и завершаться в непредсказуемом порядке, обычно рекомендуется создать обработчик сигнала SIGCHLD, вызывающий одну из функций семейства wait в цикле, пока не останется несобранных данных о дочерних процессах. Родительский процесс может полностью игнорировать завершение своих дочерних процессов и все равно не создавать зомби, но для этого требуется явное определение обработчика для SIGCHLD с помощью вызова sigaction со специальным флагом SA_NOCLDWAIT.