Из Википедии, свободной энциклопедии
Перейти к навигации Перейти к поиску

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

Unix-подобные системы [ править ]

В Unix-подобных операционных системах каждый процесс, кроме процесса 0 (swapper), создается, когда другой процесс выполняет системный вызов fork () . Процесс, вызвавший fork, является родительским процессом, а вновь созданный процесс - дочерним процессом . Каждый процесс (кроме процесса 0) имеет один родительский процесс, но может иметь много дочерних процессов.

Ядра операционной системы идентифицирует каждый процесс по его идентификатору процесса. Процесс 0 - это особый процесс, который создается при загрузке системы; после разветвления дочернего процесса (процесс 1) процесс 0 становится процессом подкачки (иногда также известным как « незанятая задача »). Процесс 1 , известный как init , является предком всех остальных процессов в системе. [1]

Linux [ править ]

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

Зомби-процессы [ править ]

Операционная система поддерживает таблицу, которая связывает каждый процесс с помощью идентификатора процесса (обычно называемого « pid ») с данными, необходимыми для его функционирования. В течение жизненного цикла процесса такие данные могут включать в себя сегменты памяти, назначенные процессу, аргументы, с которыми он был вызван, переменные среды , счетчики использования ресурсов, идентификатор пользователя, идентификатор группы и набор групп и, возможно, другие типы информации.

Когда процесс завершает свое выполнение, либо вызывая exit (даже если неявно, выполняя команду возврата из основной функции), либо получая сигнал, который вызывает его внезапное завершение, операционная система освобождает большую часть ресурсов и информации, относящейся к этот процесс, но по-прежнему сохраняет данные об использовании ресурсов и код состояния завершения , потому что родительский процесс может быть заинтересован в том, чтобы узнать, успешно ли этот дочерний процесс выполнен (с помощью стандартных функций для декодирования кода состояния завершения) и о количестве системных ресурсов, которые он расходуется во время его исполнения.

По умолчанию система предполагает, что родительский процесс действительно заинтересован в такой информации во время завершения дочернего процесса, и, таким образом, отправляет родительскому процессу сигнал SIGCHLD, чтобы предупредить о том, что есть некоторые данные о дочернем процессе, которые необходимо собрать. Такой сбор выполняется путем вызова функции семейства ожидания (либо самого ожидания , либо одного из его родственников, например, waitpid , waitid или wait4). Как только эта коллекция создана, система освобождает эти последние биты информации о дочернем процессе и удаляет его pid из таблицы процессов. Однако, если родительский процесс задерживается на сборе дочерних данных (или вообще не может этого сделать), у системы нет другого выбора, кроме как хранить pid-идентификатор дочернего процесса и данные завершения в таблице процессов на неопределенное время.

Такой завершенный процесс, данные которого не были собраны , на языке UNIX называется зомби-процессом или просто зомби . Название представляет собой юмористическую аналогию из-за рассмотрения завершенного процесса как «уже не живого» или «мертвого» - поскольку он действительно прекратил функционировать - и затяжного мертвого процесса, все еще «воплощенного» в «мире живых» процессов - процесса стол, который, следовательно, на самом деле является «нежитью» или «зомби».

Зомби-процессы могут создавать проблемы в системах с ограниченными ресурсами или с таблицами процессов ограниченного размера, поскольку создание новых активных процессов может быть предотвращено из-за нехватки ресурсов, которые все еще используются долгоживущими зомби.

Поэтому хорошей практикой программирования в любой программе, которая может порождать дочерние процессы, является наличие кода, предотвращающего формирование устойчивых зомби из исходных дочерних процессов. Самый очевидный подход - иметь код, который вызывает ожидание или один из его родственников где-то после создания нового процесса. Если ожидается, что программа создаст много дочерних процессов, которые могут выполняться асинхронно и завершаться в непредсказуемом порядке, обычно рекомендуется создать обработчик для сигнала SIGCHLD , вызывающий один из ожидающих-family функционируют в цикле до тех пор, пока не останутся несобранные дочерние данные. Родительский процесс может полностью игнорировать завершение своих дочерних процессов и по-прежнему не создавать зомби, но для этого требуется явное определение обработчика для SIGCHLD через вызов sigaction со специальным флагом опции SA_NOCLDWAIT . [3]

Сиротские процессы [ править ]

Сиротские процессы представляют собой ситуацию, противоположную зомби-процессам, поскольку они относятся к случаю, когда родительский процесс завершается раньше, чем его дочерние процессы, которые, как говорят, становятся «осиротевшими». В отличие от асинхронного родительского уведомления, которое происходит, когда дочерний процесс завершается (через сигнал SIGCHLD ), дочерние процессы не уведомляются немедленно, когда их родительский процесс завершается. Вместо этого система просто переопределяет поле «родительский PID» в данных дочернего процесса на процесс, который является «предком» любого другого процесса в системе, чей PID обычно имеет значение 1 (один) и чье имя это традиционно "init". Таким образом, было сказано, что init «принимает» каждый потерянный процесс в системе. [4] [5]

Довольно распространенное предположение программистов, плохо знакомых с UNIX, заключалось в том, что дочерние процессы завершающегося процесса будут приняты непосредственным родительским процессом этого процесса (отсюда «прародитель» этих дочерних процессов). Такое предположение было неверным - если, конечно, этот «дедушка» не был самим init.

После ядра Linux 3.4 это уже не так, фактически процессы могут выполнять системный вызов prctl () с параметром PR_SET_CHILD_SUBREAPER, и в результате они, а не процесс №1, станут родительскими для любого из своих потерянных процессов-потомков. Так работают современные сервис-менеджеры и утилиты для наблюдения за демонами, включая systemd, upstart и nosh service manager.

Это отрывок из справочной страницы, в котором сообщается, что:

Субрепер выполняет роль init (1) для своих дочерних процессов. Когда процесс становится "осиротевшим" (т. Е. Его непосредственный родитель завершается), тогда этот процесс будет передан ближайшему еще живому предку-субжатнику. Впоследствии вызовы getppid () в осиротевшем процессе теперь будут возвращать PID процесса субжатка, и когда сирота завершится, именно процесс субжатка получит сигнал SIGCHLD и сможет ждать (2) процесса. чтобы узнать его статус завершения. [6]

Ссылки [ править ]

  1. ^ Таненбаум, Эндрю (2007). Современные операционные системы (3-е изд.). Пирсон Прентис Холл. п. 752. ISBN. 0136006639.
  2. Шринивасан, Сундар (01.09.2010). «Возможности и будущее инженера: Взгляд в ядро ​​Linux - Глава 2: Создание процесса» . Sunnyeves.blogspot.com . Проверено 30 апреля 2014 .
  3. ^ "Подождите, страница руководства - Системные вызовы" . www.mankier.com .
  4. ^ "Сначала идет инициализация" .
  5. ^ «Обзор процессов Linux» . IBM. 26 марта 2012 г.
  6. ^ "Руководство программиста Linux" .

Эта статья основана на материалах, взятых из Free On-line Dictionary of Computing до 1 ноября 2008 г. и включенных в соответствии с условиями «перелицензирования» GFDL версии 1.3 или новее.