【问题标题】:How do you kill zombie process using wait()如何使用 wait() 杀死僵尸进程
【发布时间】:2015-04-12 00:16:25
【问题描述】:

我有这段代码,要求父母分叉 3 个孩子。

  • 你怎么知道(以及)将 "wait()" 语句放在哪里来杀死
    僵尸进程?

  • 如果你有 Linux,查看僵尸进程的命令是什么 虚拟盒子?

    main(){
    
     pid_t child;
     printf("-----------------------------------\n");
     about("Parent");
     printf("Now ..  Forking !!\n");
     child = fork();
     int i=0;
    
     for (i=0; i<3; i++){
        if (child < 0) {
            perror ("Unable to fork");
            break;
        } 
        else if (child == 0){
            printf ("creating child #%d\n", (i+1));
            about ("Child");
            break;
        }
    
        else{
            child = fork();
        }
      } 
    }       
    
    void about(char * msg){
    
     pid_t me;
     pid_t oldone;
    
     me = getpid();
     oldone = getppid();
    
     printf("***[%s] PID = %d   PPID = %d.\n", msg, me, oldone);
    
    }
    

【问题讨论】:

  • 如果我假设 - 我会将 wait(3) 放在 else 语句中的 child=fork() 之后。虽然我不熟悉僵尸进程或linux,所以我不太清楚如何查看僵尸进程

标签: c linux virtualbox wait zombie-process


【解决方案1】:

你怎么知道(和)把“wait()”语句放在哪里来杀死 僵尸进程?

如果您的父母只产生少量固定数量的孩子;不在乎它们何时或是否停止、恢复或完成; 本身很快就退出了,那么你就不需要使用wait()或者waitpid()来清理子进程了。 init 进程 (pid 1) 负责处理孤立的子进程,并在它们完成后清理它们。

但是,在任何其他情况下,您必须为子进程wait()。这样做可以释放资源,确保子进程已完成,并允许您获取子进程的退出状态。如果您愿意,还可以通过waitpid() 通知您何时通过信号停止或恢复孩子。

至于在哪里执行等待,

  • 您必须确保只有父母 wait()s.
  • 您应该在需要孩子完成的最早时间点或之前等待(但不是在分叉之前),或者
  • 如果你不关心这个孩子什么时候结束,是否结束,但是你需要清理资源,那么你可以定期调用waitpid(-1, NULL, WNOHANG)收集一个僵尸孩子,如果有,不阻塞。 .

特别是,您必须在fork()ing 之后立即 wait()(无条件地),因为父子进程运行相同的代码。您必须使用fork() 的返回值来确定您是在孩子中(返回值== 0),还是在父母中(任何其他返回值)。此外,只有在分叉成功时,父级必须wait(),在这种情况下,fork() 返回子级的 pid,它总是大于零。返回值小于零表示分叉失败。

您的程序实际上并不需要wait(),因为它恰好产生了四个(不是三个)孩子,然后退出。但是,如果您希望父母在任何时候最多有一个活着的孩子,那么您可以这样写:

int main() {
    pid_t child;
    int i;

    printf("-----------------------------------\n");
    about("Parent");

    for (i = 0; i < 3; i++) {
        printf("Now ..  Forking !!\n");
        child = fork();

        if (child < 0) {
            perror ("Unable to fork");
            break;
        } else if (child == 0) {
            printf ("In child #%d\n", (i+1));
            about ("Child");
            break;
        } else {
            /* in parent */
            if (waitpid(child, NULL, 0) < 0) {
                perror("Failed to collect child process");
                break;
            }
        }
    }

    return 0;
}

如果父进程在其一个或多个子进程之前退出(如果它不等待则可能发生这种情况),那么子进程此后将看到其父进程的 pid 为 1。

其他人已经回答了如何通过ps 命令获取僵尸进程列表。您还可以通过top 看到僵尸。但是,使用您的原始代码,您不太可能看到僵尸,因为父进程很快退出,然后init 将清理它留下的僵尸。

【讨论】:

    【解决方案2】:

    你怎么知道(和)在哪里放置“wait()”语句来杀死 僵尸进程?

    您可以在父进程中的任何位置使用wait(),当子进程终止时,它将从系统中删除。将它放在哪里取决于您,在您的特定情况下,您可能希望将其立即放在 child = fork(); 行之后,以便父进程在其子进程退出之前不会恢复执行。

    如果你有 Linux 虚拟机,查看僵尸进程的命令是什么?

    您可以使用ps aux 命令查看系统中的所有进程(包括僵尸进程),如果进程是僵尸进程,STAT 列将等于Z。一个示例输出是:

    USER      PID    %CPU %MEM VSZ  RSS TTY      STAT START   TIME COMMAND
    daniel    1000   0.0  0.0  0    0   ??       Z    17:15   0:00 command
    

    【讨论】:

    • 感谢您回复我。在没有wait() 的情况下对此进行测试时,在垃圾邮件编译时,我看到有时我会得到 PPID 的 1 而不是父级的 PID。在父函数中使用wait(5),我看不到任何内容。这是否意味着在函数中使用wait(5) 可以摆脱僵尸进程?
    • 另外,当我输入 ps aux 时,我最终会转到 line(?) 26433 tc。它只是垃圾邮件tc,所以我不知道在哪里看。
    • 假设你有僵尸进程,运行ps aux | grep Z 只查看包含Z 的行(如果你的程序已经完成执行,那么这不会显示任何相关信息,因为所有的僵尸子进程已从系统中删除)。至于您的第一个问题,发生的事情是您的子进程正在运行父进程退出后,因此它的父进程现在是具有pid == 1init 进程。通过调用wait,您可以阻止父进程退出,直到至少有一个子进程完成执行。
    【解决方案3】:

    你怎么知道(和)在哪里放置“wait()”语句来杀死 僵尸进程?

    您可以为 SIGCHLD 注册一个信号处理程序,将全局 volatile sig_atomic_t flag = 0 变量设置为 1。然后,在程序中的某个方便的地方,测试 flag 是否设置为 1,如果是,请将其设置回到 0 之后(否则你可能会错过一个信号)在循环中调用waitpid(-1, NULL, WNOHANG),直到它告诉你不再等待进程。请注意,该信号将使用 EINTR 中断系统调用,这是检查flag 值的好条件。如果您使用像select() 这样的无限期阻塞系统调用,您可能需要指定一个超时时间,然后再检查flag,否则您可能会错过在上一次waitpid() 调用之后但在输入之前发出的信号无限期阻塞系统调用。这个kludge的替代方法是使用pselect()

    【讨论】:

      【解决方案4】:

      用途:

      ps -e -opid,ppid,pgid,stat,etime,cmd | grep defunct
      

      要查看您的僵尸,还可以使用 ppidpgid 查看父 ID 和进程组 ID。 etime 查看僵尸存活的经过 (cpu) 时间。父 ID 对于向父进程发送自定义信号很有用。

      如果父进程被正确编码以捕获和处理SIGCHLD 信号,并且达到预期的效果(即等待/收割僵尸),那么您可以提交:

      kill -CHLD <parent_pid>
      

      告诉父母收割他们所有的僵尸。

      【讨论】:

        猜你喜欢
        • 2013-06-01
        • 2014-06-19
        • 2011-09-14
        • 1970-01-01
        • 1970-01-01
        • 2011-09-26
        • 1970-01-01
        • 1970-01-01
        • 2011-02-15
        相关资源
        最近更新 更多