【问题标题】:Zombie process and fork僵尸进程和分叉
【发布时间】:2011-02-02 10:11:02
【问题描述】:

我有这样的代码...

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

【问题讨论】:

    标签: c++ fork zombie-process dup2


    【解决方案1】:

    如果您不打算为您的子进程使用wait,请将SIGCHLD 处理程序设置为SIG_IGN 以让内核自动获取您的子进程,例如。

    signal(SIGCHLD, SIG_IGN);
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        是的,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 个答案。希望这个答案可以更清楚。谢谢。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-12
          • 1970-01-01
          • 2011-11-09
          • 2014-09-30
          相关资源
          最近更新 更多