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

у меня такой код...

c = fork();
if(c==0) {
    close(fd[READ]);

    if (dup2(fd[WRITE],STDOUT_FILENO) != -1) 
        execlp("ssh", "ssh", host, "ls" , NULL);
    _exit(1);

}   
close(fd[WRITE]);

fd[READ] и fd[WRITE] — это дескрипторы файла канала.

когда я запускаю его постоянно, когда я использую ps axe, происходит много зомби-процессов. Как это исправить? Это потому, что я не использую родителя для ожидания статуса выхода дочернего процесса...


person Prasanth Madhavan    schedule 02.02.2011    source источник


Ответы (3)


Если у вас нет намерения wait для ваших дочерних процессов, установите обработчик SIGCHLD на SIG_IGN, чтобы ядро ​​автоматически пожинало ваши дочерние процессы, например.

signal(SIGCHLD, SIG_IGN);
person Hasturkun    schedule 02.02.2011

Да, родитель должен дождаться возврата дочернего состояния. Вы можете сделать это асинхронно, перехватив SIGCHILD в родительском процессе, а затем вызвав waitpid в методе захвата.

person Benoit Thiery    schedule 02.02.2011

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

Вы можете добавить следующий код в свою программу:

if(c>0)
{
while(1){ 
ret = waitpid(-1,&status,0);

if(ret>0){
if(WIFEXITED(status)){
   if(WEXITSTATUS(status) == 0){ 
       printf("child process terminated normally and successfully\n");
   }
   else{

       printf("child process terminated normally and unsuccessfully\n");
   }
 }
else{ 

       printf("child process terminated abnormally and unsuccessfully\n");
    }
}
if(ret<0) { 
     break; 
    }
  }
}

К вашему сведению: подробнее о waitpid.

Первый параметр установлен равным -1, так что waitpid() очистит любой дочерний процесс этого родительского процесса, который в настоящее время находится в прекращенном состоянии. Первый параметр также может быть +ve - в этом случае конкретный дочерний процесс. Наиболее распространенное использование - установить для первого параметра значение -1, также обратитесь к справочной странице waitpid(). Второй параметр используется для извлечения кода состояния завершения/выхода дочернего процесса — API системного вызова waitpid() заполняет поле статуса при вызове API системного вызова. Последнее поле - это поле флагов - в настоящее время не используется - в большинстве случаев поле флагов будет установлено на 0 - это означает, что поведение системного вызова API по умолчанию !!! если вам действительно нужно использовать флаги, обратитесь к справочной странице waitpid().

Примечание. В отправленном вами коде _exit(1) будет вызываться в случае сбоя execlp(). поэтому вы можете поставить условие для отказа execlp(), и это условие _exit() может быть вызвано. Причина в том, что функции execlp() возвращаются только в случае возникновения ошибки.

Модифицированный код может выглядеть следующим образом:

c = fork();
if(c==0) {
close(fd[READ]);

if (dup2(fd[WRITE],STDOUT_FILENO) != -1) 
    ret_execlp = execlp("ssh", "ssh", host, "ls" , NULL);
if(ret_execlp == -1 ) {
      printf("execlp is failed");
      _exit(1);
   }
}
close(fd[WRITE]);

Я ценю приведенные выше 2 ответа. Хотелось бы, чтобы этот ответ дал больше ясности. Спасибо.

person Prashanth Reddy    schedule 07.08.2013