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

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

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

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

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

Содержание
  • 1 Обзор
  • 2 Пример
    • 2.1 Выход
    • 2.2 Пояснение
  • 3 См. Также
  • 4 Ссылки
  • 5 Внешние ссылки
Обзор

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

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

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

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

Пример

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

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

Вывод

parent9 Child3 Child4 Child2 Child5 Child1 Child6 Child0 Child7 Child8 Child9 // здесь есть пауза parent8 parent7 parent6 parent5 parent4 parent3 parent2 parent1 parent0

объяснение

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

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

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

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

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-23 11:08:49
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте