2

我有这样的代码...

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 时有很多僵尸进程。如何纠正这种情况?这是因为我没有使用父进程等待子进程的退出状态...

4

3 回答 3

7

如果您不打算wait为您的子进程设置SIGCHLD处理程序以SIG_IGN让内核自动收割您的子进程,例如。

signal(SIGCHLD, SIG_IGN);
于 2011-02-02T10:19:53.310 回答
2

是的,父母必须等待孩子返回状态。您可以通过SIGCHILD在父进程中捕获然后调用waitpid捕获方法来异步执行此操作。

于 2011-02-02T10:13:25.170 回答
0

是的,应该从父级调用 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 - 在这种情况下,waitpid() 将只清理具体的子进程。最常见的用法是将第一个参数设置为-1,也可以参考waitpid()的手册页。第二个参数用于提取子进程的终止/退出状态码——waitpid()系统调用API在调用系统调用API时填充状态字段。最后一个字段是标志字段 - 目前未使用 - 在大多数情况下,标志字段将设置为 0 - 意思是系统调用 API 的默认行为!如果您确实需要使用标志,请参阅 waitpid() 的手册页。

注意:在您提交的代码中,如果 execlp() 失败,将调用 _exit(1)。所以你可以为 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个答案。希望这个答案可以更清楚。谢谢你。

于 2013-08-07T09:49:50.263 回答