Зомби процесс и вилка - PullRequest
2 голосов
/ 02 февраля 2011

У меня есть такой код ...

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 ax.Как это исправить?Это потому, что я не использую родителя для ожидания состояния выхода дочернего процесса ...

Ответы [ 3 ]

7 голосов
/ 02 февраля 2011

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

signal(SIGCHLD, SIG_IGN);
2 голосов
/ 02 февраля 2011

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

0 голосов
/ 07 августа 2013

Да, waitpid () должен вызываться из parent. 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 - в этом случае waitpid () очистит только конкретный дочерний процесс. Чаще всего для первого параметра устанавливается значение -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 ответа. Жаль, что этот ответ может дать больше ясности. Спасибо.

...