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

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

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

Зомби-процессы не следует путать с потерянными процессами : сиротский процесс - это процесс, который все еще выполняется, но родитель которого умер. Когда родитель умирает, осиротевший дочерний процесс принимается init(идентификатор процесса 1). Когда процессы-сироты умирают, они не остаются как процессы-зомби; вместо этого они waitподпевают init. В результате процесс, который одновременно является зомби и сиротой, будет завершен автоматически.

Обзор [ править ]

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

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

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

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

Пример [ править ]

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

# включить  <sys / wait.h>#include  <stdlib.h>#include  <unistd.h>int  main ( пусто ){  pid_t  pids [ 10 ];  int  i ;для  ( я  =  9 ;  я  > =  0 ;  - я )  {  pids [ я ]  =  вилка ();  если  ( pids [ i ]  ==  0 )  {  printf ( "Дочерний% d \ n " , i );  спать ( я + 1 );  _exit ( 0 );  } }for  ( я  =  9 ;  я  > =  0 ;  - я ) {  printf ( "родитель% d \ n " , я );  waitpid ( pids [ i ],  NULL ,  0 );  } return  0 ; }

Вывод [ править ]

родитель9Ребенок3Ребенок4Ребенок2Детский5Ребенок1Детский6Детский0Детский7Детский8Child9 // здесь паузаparent8parent7родитель6parent5parent4parent3parent2parent1parent0

Объяснение [ править ]

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

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

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

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

См. Также [ править ]

  • Вилочная бомба
  • Зомби-объект
  • Непрерывный сон

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

  1. ^ "подождите (2) Man Page" . Руководство программиста Linux .
  2. ^ «Зомби (5) - UNIX System V (Концепции)» . Детектор коллайдера в Фермилабе .
  3. ^ https://stackoverflow.com/questions/42627411/can-someone-please-explain-how-this-worksfork-sleep
  • "Страницы руководства UNIX: ps ()" . UNIXhelp для пользователей . Архивировано из оригинала на 2013-03-08.

Внешние ссылки [ править ]

  • Зомби процесс usenet сообщение
  • Часто задаваемые вопросы по UNIX Вопрос 3.13: Как избавиться от упорных процессов-зомби?