stringtranslate.com

Процесс зомби

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

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

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

Обзор

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

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

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

Чтобы удалить зомби из системы, сигнал 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 ;      для ( i = 9 ; i >= 0 ; -- i ) { pids [ i ] = fork (); если ( pids [ i ] == 0 ) { printf ( "Ребенок%d \n " , i ); sleep ( i + 1 ); _exit ( 0 ); } }                       для ( i = 9 ; i >= 0 ; -- i ) { printf ( "parent%d \n " , i ); waitpid ( pids [ i ], NULL , 0 ); }               вернуть 0 ; } 

Выход

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

Объяснение

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

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

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

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

Смотрите также

Ссылки

  1. ^ "wait(2) Man Page". Руководство программиста Linux .
  2. ^ "Зомби(5) - UNIX System V (Концепции)". Детектор коллайдера в Фермилабе .
  3. ^ "Linux - Может ли кто-нибудь объяснить, как это работает?fork(),sleep()".

Внешние ссылки