Jump to content

Зомби-процесс

В Unix и Unix-подобных компьютерных операционных системах процесс -зомби или несуществующий процесс — это процесс , выполнение которого завершилось (посредством exit системный вызов ), но все еще имеет запись в таблице процессов : это процесс в « завершенном состоянии ». Это происходит для дочерних процессов , где запись по-прежнему необходима, чтобы позволить родительскому процессу прочитать статус завершения своего дочернего процесса : как только статус завершения будет прочитан через wait системный вызов , запись о зомби удаляется из таблицы процессов и считается, что она «пожата». Дочерний процесс изначально становится зомби, и только затем его удаляют из таблицы ресурсов. При нормальной работе системы зомби немедленно поджидают их родители, а затем система их пожинает. Процессы, которые остаются зомби в течение длительного времени, обычно являются ошибками и могут вызвать утечку ресурсов . Как правило, единственный ресурс ядра, который они занимают, — это запись таблицы процессов, их идентификатор процесса. Однако зомби также могут держать буферы открытыми, потребляя память. Зомби могут удерживать дескрипторы файловых дескрипторов, что предотвращает доступность места для этих файлов для файловой системы. Этот эффект можно увидеть по разнице между du и df. Пока du может показывать большой объем свободного дискового пространства, df покажет полный раздел. Если зомби не очистить, это может привести к заполнению корневого раздела и краху системы.

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

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

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

После удаления зомби его идентификатор процесса (PID) и запись в таблице процессов можно использовать повторно. Однако, если родитель не позвонит wait, зомби останется в таблице процессов, что приведет к утечке ресурсов . В некоторых ситуациях это может быть желательно — родительский процесс хочет продолжать удерживать этот ресурс — например, если родительский процесс создает другой дочерний процесс, он гарантирует, что ему не будет назначен тот же PID. В современных UNIX-подобных системах (которые в этом отношении соответствуют спецификации SUSv3 ) применяется следующий особый случай: если родительский элемент явно игнорирует SIGCHLD, установив для его обработчика значение SIG_IGN (вместо того, чтобы просто игнорировать сигнал по умолчанию) или имеет SA_NOCLDWAIT установлен флаг, вся информация о статусе дочернего завершения будет удалена и не останется никаких процессов-зомби. [1]

Зомби можно идентифицировать по выводам Unix. ps командование наличием " Z" в столбце "СТАТ". [2] Зомби, существующие более короткого периода времени, обычно указывают на ошибку в родительской программе или просто на необычное решение не создавать потомков (см. пример). Если родительская программа больше не работает, процессы-зомби обычно указывают на ошибку в операционной системе. Как и в случае с другими утечками ресурсов, присутствие нескольких зомби само по себе не вызывает беспокойства, но может указывать на проблему, которая может стать серьезной при более высоких нагрузках. Поскольку процессам-зомби не выделяется память (системная память используется только для самой записи таблицы процессов), основная проблема многих зомби заключается не в нехватке памяти, а, скорее, в нехватке записей таблицы процессов, в частности, идентификаторов процессов. Однако зомби могут удерживать открытые буферы, связанные с файловыми дескрипторами, и тем самым вызывать потребление памяти зомби. Зомби также могут хранить файловый дескриптор удаленного файла. Это не позволяет файловой системе восстановить i-узлы удаленного файла. Таким образом, команда отображения использования диска не будет учитывать удаленные файлы, пространство которых не может быть повторно использовано из-за зомби, удерживающего файловый дескриптор.

Чтобы удалить зомби из системы, сигнал SIGCHLD можно отправить родительскому элементу вручную, используя команду kill команда. Если родительский процесс по-прежнему отказывается пожинать зомби и можно завершить родительский процесс, следующим шагом может быть удаление родительского процесса. Когда процесс теряет своего родителя, init становится его новым родителем. init периодически выполняет wait системный вызов, чтобы собрать зомби с помощью init как родитель.

Синхронное ожидание определенных дочерних процессов в (конкретном) порядке может привести к тому, что зомби будут присутствовать дольше, чем вышеупомянутый «короткий период времени». Это не обязательно ошибка программы.

#include <sys/wait.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(void){    pid_t pids[10];    int i;    for (i = 9; i >= 0; --i) {        pids[i] = fork();        if (pids[i] == 0) {            printf("Child%d\n", i);            sleep(i+1);            _exit(0);        }    }    for (i = 9; i >= 0; --i) {        printf("parent%d\n", i);        waitpid(pids[i], NULL, 0);    }    return 0;}
parent9Child3Child4Child2Child5Child1Child6Child0Child7Child8Child9 // there is a pause hereparent8parent7parent6parent5parent4parent3parent2parent1parent0

Объяснение

[ редактировать ]

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

Во время цикла создается массив идентификаторов дочерних процессов. Копия массива pids[] существует во всех 11 процессах, но только в родительском процессе она является полной — в копии каждого дочернего процесса будут отсутствовать дочерние PID с меньшими номерами, а собственный PID будет иметь нулевой номер. (Не то чтобы это имело большое значение, поскольку фактически этот массив использует только родительский процесс.)

Второй цикл выполняется только в родительском процессе (поскольку все дочерние процессы завершились до этого момента) и ожидает выхода каждого дочернего процесса. Он ждет ребенка, который спал 10 секунд первым; все остальные уже давно вышли, поэтому все сообщения (кроме первого) появляются один за другим. Здесь нет возможности случайного упорядочения, поскольку оно управляется циклом в одном процессе. Первое родительское сообщение фактически появилось раньше любого из дочерних сообщений — родительский элемент смог перейти во второй цикл до того, как какой-либо из дочерних процессов смог запуститься. Опять же, это просто случайное поведение планировщика процессов — сообщение «parent9» могло появиться где угодно в последовательности до «parent8».

Child0–Child8 проводят в этом состоянии одну или несколько секунд между моментом выхода и моментом, когда родитель выполнил для них waitpid(). Родитель уже ждал Child9 перед его завершением, так что один процесс практически не находился в состоянии зомби. [3]

См. также

[ редактировать ]
  1. ^ "wait(2) Страница руководства" . Руководство программиста Linux .
  2. ^ «Зомби(5) — UNIX System V (Концепции)» . Детектор коллайдеров в Фермилабе .
  3. ^ «Linux. Может кто-нибудь объяснить, как это работает? fork(),sleep()» .
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 38ea20228f37672f9d2a8612c7f1c6e4__1706203440
URL1:https://arc.ask3.ru/arc/aa/38/e4/38ea20228f37672f9d2a8612c7f1c6e4.html
Заголовок, (Title) документа по адресу, URL1:
Zombie process - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)