linux - 使子进程在 waitpid 之前不是僵尸进程

标签 linux unix process waitpid

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

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

如果我对退出代码不感兴趣,是否有办法将特定的子进程标记为静静地自行消亡?

最佳答案

你总是需要等待一个子进程,但是如果你遵循这个过程,那么你可以等待一个很快就会死掉的子进程,让 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;
}

各种 sleep 持续时间应该允许您看到以下事件(观看 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

第二步

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

第 3 步

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

关于linux - 使子进程在 waitpid 之前不是僵尸进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42765329/

相关文章:

python - 使用子进程在 python 2.7 中获取尾命令输出

linux - 如何在相同的环境下生成新的 xterm

java - 在 Java/Linux 中使用命名管道时流未正确关闭

c - 在进程通信中作为标准输入/标准输出的管道。

在 netfilter 模块中计算 TCP 校验和

sql - lsof 如果文件描述符已打开

excel - Shell 脚本 - 将 Excel (xlsx) 转换为 CSV - 删除空格/制表符空间

bash - 如何根据文件自动创建符号链接(symbolic link)?

unix - 使用 curl 或 wget.. 从 artifactory 下载 docker 图像?

java - 如何在 Android 应用程序中获取 logcat -v 时间?