【问题标题】:Make child process not zombie until waitpid让子进程直到waitpid才成为僵尸
【发布时间】:2017-03-13 13:52:04
【问题描述】:

是否有 Linux 或 POSIX 方法来指示进程在完成且父进程不调用 waitpid() 时不要变成僵尸?

我知道我们可以将SA_NOCLDSTOP 用于SIGCHLD 处理程序的父进程,但在我的情况下这不是一个选项,因为父进程很忙,而SIGCHLD 正在用于其他事情。

如果我对退出代码不感兴趣,有没有办法将特定的子进程标记为自己安静地死掉?

【问题讨论】:

    标签: linux unix process waitpid


    【解决方案1】:

    你总是需要等待一个子进程,但是如果你遵循这个过程,那么你可以等待一个很快就会死掉的子进程,然后让 init 继承你的“真实”进程。然后 Init 会为你整理。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    void main(void) {
        int ret;
        pid_t child1;
        pid_t child2;
        int status;
    
        child1 = fork();
        if (child1 == -1) {
            /* error */
            exit(1);
        }
    
        if (child1 == 0) {
            /* in the child... we create a new session, and then re-fork */
            setsid();
    
            child2 = fork();
            if (child2 == -1) {
                exit(1);
            }
    
            if (child2 == 0) {
                /* call execve() or a friend */
                ret = execlp("sleep", "sleep", "6", NULL);
    
                /* we should _never_ get here - unless the execlp() fails */
                fprintf(stderr, "execlp() returned: %d\n", ret);
                exit(1);
                for(;;);
            }
    
            sleep(2); 
    
            /* success ... child1 dies here */
            exit(0);
        }
    
        sleep(4);
    
        ret = waitpid(child1, &status, 0);
        if (ret != 0) {
            /* unfortunately we can only determine the state of our 'proxy' process...
             * to get any further information / the child-child PID, then you'll need to use a pipe to share the information */
            fprintf(stderr, "waitpid() returned %d\n", ret);
        }
    
        sleep(4); 
    
        return;
    }
    

    不同的睡眠持续时间应该能让你看到以下事件(观看top 或其他东西)。

    第一步

    所有进程都启动,所有进程都作为 shell 的子级链接

    • 17336 - 我的外壳
    • 21855 - 应用程序
    • 21856 - Child1(代理进程)
    • 21857 - Child2(有用的子进程)

    top 输出:

    attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
    attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
    attie    21856 21855  0 16:34 ?        00:00:00 ./test
    attie    21857 21856  0 16:34 ?        00:00:00 sleep 6
    

    第 2 步

    Child1 死了,变成了僵尸/不复存在,Child2 被 init (PID 1) 继承

    attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
    attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
    attie    21856 21855  0 16:34 ?        00:00:00 [test] <defunct>
    attie    21857     1  0 16:34 ?        00:00:00 sleep 6
    

    第三步

    Child1 在调用 waidpid()

    时被父母清除
    attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
    attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
    attie    21857     1  0 16:34 ?        00:00:00 sleep 6
    

    第四步

    Child2 死亡,并被 init 清除

    attie    17336 17335  0 16:04 pts/36   00:00:00 -bash
    attie    21855 17336  0 16:34 pts/36   00:00:00 ./test
    

    【讨论】:

      猜你喜欢
      • 2014-05-09
      • 2016-07-03
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 2012-06-07
      相关资源
      最近更新 更多