Создать зомби-процесс

Я заинтересован в создании процесса зомби. Насколько я понимаю, процесс зомби происходит, когда родительский процесс завершается до дочернего процесса. Однако я попытался воссоздать процесс зомби, используя следующий код:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main ()
{
  pid_t child_pid;

  child_pid = fork ();
  if (child_pid > 0) {
    exit(0);
  }
  else {
    sleep(100);
    exit (0);
  }
  return 0;
}

Однако этот код завершается сразу после ожидаемого выполнения. Однако, как я

ps aux | grep a.out

Я обнаружил, что a.out работает как обычный процесс, а не как зомби-процесс, как я ожидал.

Я использую ОС Ubuntu 14.04 64 бит.


person user3354832    schedule 07.08.2014    source источник
comment
Ваш код в вопросе не создает зомби-процесс, потому что в вашем коде родительский процесс завершается первым, а дочерний процесс продолжает работать. (Помните, что fork() возвращает 0 в дочернем процессе и PID дочернего процесса в родительском процессе.) Чтобы увидеть зомби-процесс, вам нужно заставить дочерний процесс выйти, пока родитель еще жив, но не ждал дочерний процесс. Если вы просто измените строку 10 вашего кода с if (child_pid > 0) на if (child_pid == 0), это исправит ваш код, и вы сможете увидеть процесс-зомби, когда дочерний процесс завершится.   -  person Susam Pal    schedule 15.12.2015


Ответы (2)


Цитата:

Насколько я понимаю, процесс зомби происходит, когда родительский процесс завершается до дочернего процесса.

Это не правильно. Согласно man 2 wait (см. ПРИМЕЧАНИЯ):

Ребенок, который прекращает свое существование, но его не ждали, становится «зомби».

Таким образом, если вы хотите создать зомби-процесс, после fork(2) дочерний процесс должен exit(), а родительский процесс должен sleep() перед выходом, что дает вам время понаблюдать за выводом ps(1).

Например, вы можете использовать приведенный ниже код вместо своего и использовать ps(1) во время sleep()ing:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid;
    int status;

    if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
    }

    /* Child */
    if (pid == 0)
        exit(0);

    /* Parent
     * Gives you time to observe the zombie using ps(1) ... */
    sleep(100);

    /* ... and after that, parent wait(2)s its child's
     * exit status, and prints a relevant message. */
    pid = wait(&status);
    if (WIFEXITED(status))
        fprintf(stderr, "\n\t[%d]\tProcess %d exited with status %d.\n",
                (int) getpid(), pid, WEXITSTATUS(status));

    return 0;
}
person chrk    schedule 10.08.2014
comment
Большое спасибо чрк! Я попробовал ваш код и увидел несколько зомби-процессов. Но у меня есть еще одна забота. Почему мой код не создает зомби-процесс? Согласно определению в вашем сообщении, завершается ли дочерний процесс без ожидания родителем (родительский процесс был завершен без команды ожидания). @chrk - person user3354832; 12.08.2014
comment
@user3354832 user3354832 Ваш код в вопросе не создает зомби-процесс, потому что в вашем коде родительский процесс завершается первым, а дочерний продолжает работать. (Помните, что fork() возвращает 0 в дочернем процессе и PID дочернего процесса в родительском процессе.) Чтобы увидеть зомби-процесс, вам нужно заставить дочерний процесс выйти, пока родитель еще жив, но не ждал дочерний процесс. Если вы просто измените строку 10 вашего кода с if (child_pid > 0) на if (child_pid == 0), это исправит ваш код, и вы сможете увидеть процесс-зомби, когда дочерний процесс завершится. - person Susam Pal; 15.12.2015
comment
Просто чтобы уточнить немного больше. Если родитель завершается первым, происходит то, что дочерний элемент теперь является сиротой (его родитель умер), и процесс инициализации примет его (поэтому новый родитель имеет pid 1). В процессе инициализации зарегистрирован специальный обработчик, который получает уведомление о смерти дочернего процесса, поэтому, когда дочерний процесс умирает, он будет ждать, пока он прочитает свой код состояния, и, следовательно, дочерний процесс не станет зомби. Если бы процесс инициализации не делал этого (например, при работе внутри докера), у вас все равно был бы зомби с вашей версией. - person Moises Silva; 16.01.2019

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

Ниже приведена программа c для создания зомби-процесса в нашей системе. Сохраните этот файл как зомби.c:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main ()
{
  pid_t child_pid;

  child_pid = fork ();
  if (child_pid > 0) {
    sleep (60);
  }
  else {
    exit (0);
  }
  return 0;
}

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

Скомпилируйте эту программу

gcc zombie.c

Теперь запустите программу-зомби:

./a.out

Команда ps теперь также покажет этот несуществующий процесс, откроет новый терминал и использует следующую команду для проверки несуществующего процесса:

aamir@aamir:~/process$ ps -ef | grep a.out
aamir    10171  3052  0 17:12 pts/0    00:00:00 ./a.out
aamir    10172 10171  0 17:12 pts/0    00:00:00 [a.out] <defunct> #Zombie process
aamir    10177  3096  0 17:12 pts/2    00:00:00 grep --color=auto a.out
person Aamir Akbari    schedule 20.12.2020