你怎么用wait()杀死僵尸进程

时间:2015-02-11 15:02:21

标签: c linux virtualbox wait zombie-process

我有这个代码,需要父母分叉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);
    
    }
    

4 个答案:

答案 0 :(得分:8)

  

你怎么知道(和)把#34; wait()&#34;放在哪里?要杀人的说法   僵尸进程?

如果您的父母只产生一小部分固定数量的孩子;不关心他们何时或是否停止,恢复或完成; 本身会快速退出,然后您无需使用wait()waitpid()来清理子进程。 init进程(pid 1)负责处理孤立的子进程,并在完成后对其进行清理。

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

至于,其中执行等待,

  • 您必须确保仅限父 wait()
  • 您应该在您需要孩子完成的最早时间或之前等待(但不是在分叉之前),或者
  • 如果您不关心孩子何时或是否完成,但您需要清理资源,那么您可以定期致电waitpid(-1, NULL, WNOHANG)以收集一个僵尸孩子(如果有的话),如果有的话不是任何人。

特别是,wait()之后,您必须立即 fork()(无条件地),因为父级和子级运行相同的代码。必须使用fork()的返回值来确定您是否在子项中(返回值== 0),还是在父项中(任何其他返回值)。此外,只有在分叉成功的情况下,父母才必须wait(),在这种情况下,fork()会返回孩子的pid,该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将清除它留下的僵尸。

答案 1 :(得分:1)

  

你怎么知道(和)将“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

答案 2 :(得分:0)

  

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

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

答案 3 :(得分:0)

使用:

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

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

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

kill -CHLD <parent_pid>

告诉父母收割所有僵尸。