Родительский процесс
![]() | В этой статье есть несколько проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
В вычислительной технике родительский процесс — это процесс, создавший один или несколько дочерних процессов .
Unix-подобные системы
[ редактировать ]В Unix-подобных операционных системах каждый процесс, кроме процесса 0 (своппера), создается, когда другой процесс выполняет fork() системный вызов . Процесс, вызвавший fork, является родительским процессом , а вновь созданный процесс — дочерним процессом . Каждый процесс (кроме процесса 0) имеет один родительский процесс, но может иметь множество дочерних процессов.
Ядро операционной системы идентифицирует каждый процесс по его идентификатору процесса. Процесс 0 — это специальный процесс, который создается при загрузке системы; после разветвления дочернего процесса (процесса 1) процесс 0 становится процессом подкачки (иногда его также называют « простой задачей »). Процесс 1 , известный как init является предком всех остальных процессов в системе. [1]
Линукс
[ редактировать ]В ядре Linux , в котором существует очень небольшая разница между процессами и потоками POSIX , существует два типа родительских процессов, а именно настоящий родительский и родительский. Родительский процесс — это процесс, который получает сигнал SIGCHLD при завершении дочернего процесса, тогда как настоящий родительский процесс — это поток, который фактически создал этот дочерний процесс в многопоточной среде. Для обычного процесса оба этих значения одинаковы, но для потока POSIX, действующего как процесс, эти два значения могут быть разными. [2]
Зомби-процессы
[ редактировать ]Операционная система поддерживает таблицу, которая связывает каждый процесс посредством его идентификатора процесса (обычно называемого « pid ») с данными, необходимыми для его функционирования. В течение жизни процесса такие данные могут включать сегменты памяти, назначенные процессу, аргументы, с которыми он был вызван, переменные среды , счетчики использования ресурсов, идентификатор пользователя, идентификатор группы и набор групп, а также, возможно, другие типы информации.
Когда процесс завершает свое выполнение либо путем вызова выхода (даже если неявно, путем выполнения команды возврата из основной функции), либо путем получения сигнала , который вызывает его внезапное завершение, операционная система освобождает большую часть ресурсов и информации, относящейся к процессу. этот процесс, но по-прежнему сохраняет данные об использовании ресурсов и коде состояния завершения , поскольку родительский процесс может быть заинтересован в том, чтобы узнать, успешно ли выполнился этот дочерний процесс (путем использования стандартных функций для декодирования кода состояния завершения) и объем системных ресурсов, которые он потребляется во время его выполнения.
По умолчанию система предполагает, что родительский процесс действительно заинтересован в такой информации в момент завершения дочернего процесса, и поэтому отправляет родительскому процессу сигнал SIGCHLD , предупреждающий о наличии некоторых данных о дочернем процессе, которые необходимо собрать. Такой сбор осуществляется путем вызова функции семейства wait (либо самой функции wait , либо одной из ее родственников, например waitpid , waitid или wait4 ). Как только этот сбор собран, система публикует последние биты информации о дочернем процессе и удаляет его pid из таблицы процессов. Однако если родительский процесс задерживается со сбором данных дочернего процесса (или вообще не делает этого), у системы не остается иного выбора, кроме как хранить pid дочернего процесса и данные завершения в таблице процесса на неопределенный срок.
называется процессом-зомби или просто зомби Такой завершенный процесс, данные которого не были собраны, на языке UNIX . Название представляет собой юмористическую аналогию, поскольку завершенный процесс рассматривается как «уже не живой» или «мертвый» (поскольку он действительно перестал функционировать) и затянувшийся мертвый процесс, все еще «воплощенный» в «мире живых» процессов - процесс стол, который, следовательно, на самом деле является «нежитью» или «зомби».
Процессы-зомби могут создавать проблемы в системах с ограниченными ресурсами или таблицами процессов ограниченного размера, поскольку создание новых активных процессов может быть предотвращено из-за нехватки ресурсов, которые все еще используются долгоживущими зомби.
Поэтому хорошей практикой программирования в любой программе, которая может порождать дочерние процессы, является наличие кода, предотвращающего образование долгоживущих зомби из исходных дочерних процессов. Самый очевидный подход — разместить где-нибудь код, который вызывает wait или один из его родственников после создания нового процесса. Если ожидается, что программа создаст множество дочерних процессов, которые могут выполняться асинхронно и завершаться в непредсказуемом порядке, обычно полезно создать обработчик для сигнала SIGCHLD , вызывая одну из функций семейства wait в цикле до тех пор, пока не останется несобранных дочерних процессов. данные остаются. Родительский процесс может полностью игнорировать завершение своих дочерних процессов и при этом не создавать зомби, но для этого требуется явное определение обработчика SIGCHLD посредством вызова sigaction со специальным флагом опции SA_NOCLDWAIT . [3]
Сиротские процессы
[ редактировать ]Сиротские процессы представляют собой ситуацию, противоположную процессам-зомби, и относятся к случаю, когда родительский процесс завершается раньше, чем его дочерние процессы, которые, как говорят, становятся «сиротскими». В отличие от асинхронного уведомления от дочернего процесса к родительскому, которое происходит при завершении дочернего процесса (через SIGCHLD ), дочерние процессы не уведомляются сразу после завершения работы родительского процесса. Вместо этого система просто переопределяет поле «родительский PID» в данных дочернего процесса, чтобы оно было процессом, который является «предком» любого другого процесса в системе, чей PID обычно имеет значение 1 (единица) и чье имя традиционно является «init» (за исключением ядра Linux 3.4 и выше [подробнее ниже]). Таким образом, было сказано, что init «принимает» каждый потерянный процесс в системе. [4] [5]
Программисты, плохо знакомые с UNIX, довольно часто предполагали, что дочерние процессы завершающегося процесса будут приняты непосредственным родительским процессом этого процесса (отсюда и «прародительский» процесс этих дочерних процессов). Такое предположение было неверным – если, конечно, этот «прародитель» не был самим init.
После ядра Linux 3.4 это уже не так, фактически процессы могут выполнять системный вызов prctl() с опцией PR_SET_CHILD_SUBREAPER, и в результате они, а не процесс № 1, станут родительскими для любого из своих осиротевших процессов-потомков. Именно так работают современные менеджеры сервисов и утилиты управления демонами, включая systemd, upstart и менеджер сервисов nosh.
Это краткое изложение страницы руководства, в котором сообщается, что:
Поджнец выполняет роль init(1) для своих дочерних процессов. Когда процесс становится осиротевшим (т. е. его непосредственный родитель завершается), тогда этот процесс будет передан в родительское состояние ближайшему еще живому предку-поджнецу. Впоследствии вызовы getppid() в потерянном процессе теперь будут возвращать PID процесса-поджнеца, а когда потерянный процесс завершается, именно процесс-поджнец будет получит сигнал SIGCHLD и сможет ждать (2) процесса, чтобы узнать статус его завершения. [6]
Ссылки
[ редактировать ]- ^ Таненбаум, Эндрю (2007). Современные операционные системы (3-е изд.). Пирсон Прентис Холл. п. 752. ИСБН 978-0136006633 .
- ^ Шринивасан, Сундар (1 сентября 2010 г.). «Возможности и будущее инженера: краткий обзор ядра Linux - Глава 2: Создание процесса» . Sunnyeves.blogspot.com . Проверено 30 апреля 2014 г.
- ^ «Справочная страница ожидания — Системные вызовы» . www.mankier.com .
- ^ «init на первом месте» .
- ^ «Обзор процессов Linux» . ИБМ. 26 марта 2012 г.
- ^ «Руководство программиста Linux» .