Как вы убиваете процесс зомби, используя wait()

У меня есть этот код, который требует родителя для fork 3 детей.

  • Как вы знаете (и), куда положить оператор "wait()" , чтобы убить зомби-процессы?

  • Что такое команда для просмотра процессов зомби, если у вас есть Linux виртуальный ящик?

    main(){
     pid_t child;
     printf("-----------------------------------\n");
     about("Parent");
     printf("Now .. Forking !!\n");
     child = fork();
     int i=0;
     for (i=0; i<3; i++){
     if (child < 0) {
     perror ("Unable to fork");
     break;
     } 
     else if (child == 0){
     printf ("creating child #%d\n", (i+1));
     about ("Child");
     break;
     }
     else{
     child = fork();
     }
     } 
    } 
    void about(char * msg){
     pid_t me;
     pid_t oldone;
     me = getpid();
     oldone = getppid();
     printf("***[%s] PID = %d PPID = %d.\n", msg, me, oldone);
    }
3 ответа

Как вы знаете (и), где положить оператор wait(), чтобы убить зомби?

Если ваш родитель порождает только небольшое фиксированное количество детей; не имеет значения, когда они останавливаются, возобновляются или заканчиваются; и быстро выходят, тогда вам не нужно использовать wait() или waitpid() для очистки дочерних процессов. Процесс init (pid 1) берет на себя ответственность за осиротевшие дочерние процессы и очищает их, когда они заканчиваются.

Однако при любых других обстоятельствах вы должны wait() для дочерних процессов. Выполнение этого освобождает ресурсы, гарантирует, что ребенок закончен, и позволяет вам получить статус выхода ребенка. Через waitpid() вы также можете получать уведомление, когда ребенок остановлен или возобновлен сигналом, если вы этого пожелаете.

Как для того, чтобы выполнить ожидание,

  • Вы должны убедиться, что только родительский wait() s.
  • Вам следует подождать до или до самой ранней точки, где вам нужно, чтобы ребенок закончил (но не до форкирования), OR
  • если вам все равно, когда ребенок закончил, но вам нужно очистить ресурсы, вы можете периодически называть waitpid(-1, NULL, WNOHANG) собирать ребенка-зомби, если он есть, без блокировки, если нет.

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

Ваша программа действительно не нуждается в wait(), потому что она порождает ровно четыре (не три) дочерних элемента, а затем завершает работу. Однако, если вы хотите, чтобы у родителя было не более одного живого ребенка в любое время, вы можете написать его следующим образом:

int main() {
 pid_t child;
 int i;
 printf("-----------------------------------\n");
 about("Parent");
 for (i = 0; i < 3; i++) {
 printf("Now .. Forking !!\n");
 child = fork();
 if (child < 0) {
 perror ("Unable to fork");
 break;
 } else if (child == 0) {
 printf ("In child #%d\n", (i+1));
 about ("Child");
 break;
 } else {
 /* in parent */
 if (waitpid(child, NULL, 0) < 0) {
 perror("Failed to collect child process");
 break;
 }
 }
 }
 return 0;
}

Если родительский элемент выходит из одного или нескольких его дочерних элементов, что может произойти, если он не дожидается, тогда ребенок будет видеть, что его родительский процесс является pid 1.

Другие уже ответили, как получить список процессов зомби с помощью команды ps. Вы также можете увидеть зомби через top. Однако с вашим исходным кодом вы вряд ли поймаете проблеск зомби, потому что родительский процесс выходит очень быстро, а init очистит оставшихся зомби.


Как вы знаете (и), где положить оператор wait(), чтобы убить зомби?

Вы можете использовать wait() в любом месте родительского процесса, а когда дочерний процесс завершается, он будет удален из системы. В любом случае, в вашем конкретном случае вы, вероятно, захотите поместить его сразу после строки child = fork();, чтобы родительский процесс не возобновил выполнение, пока его дочерний элемент не выйдет.

Что такое команда для просмотра процессов зомби, если у вас есть виртуальная яма Linux?

Вы можете использовать команду ps aux для просмотра всех процессов в системе (включая процессы зомби), а столбец STAT будет равен Z, если этот процесс является зомби. Пример вывода:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
daniel 1000 0.0 0.0 0 0 ?? Z 17:15 0:00 command


Как вы знаете (и), где положить оператор wait(), чтобы убить зомби?

Вы можете зарегистрировать обработчик сигнала для SIGCHLD, который устанавливает глобальную переменную volatile sig_atomic_t flag = 0 в 1. Затем, в каком-то удобном месте в вашей программе, проверьте, установлено ли значение flag равным 1, и, если да, установите его обратно до 0 и далее (иначе вы можете пропустить сигнал) вызовите waitpid(-1, NULL, WNOHANG) в цикле, пока он не сообщит вам, что больше не нужно ждать процессов. Обратите внимание, что сигнал будет прерывать системные вызовы с EINTR, что является хорошим условием для проверки значения flag. Если вы используете бесконечно блокирующий системный вызов типа select(), вам может потребоваться указать тайм-аут, после которого вы проверите flag, так как в противном случае вы можете пропустить сигнал, который был поднят после вашего последнего вызова waitpid(), но перед входом в бесконечно блокирующий системный вызов. Альтернативой этому kludge является использование pselect().

licensed under cc by-sa 3.0 with attribution.