【问题标题】:How to prevent creation of zombie processes while using fork() and exec() in Linux?在 Linux 中使用 fork() 和 exec() 时如何防止创建僵尸进程?
【发布时间】:2015-02-06 07:11:06
【问题描述】:

当我使用 fork() 和 exec() 在后台运行应用程序时,有什么方法可以防止创建僵尸进程?父母不应该 wait() 等待孩子完成。我也不能使用 sigaction() 和 sigaction.sa_handler 因为它会影响我不想要的所有子进程。我想要一些只会收获那个特定孩子的东西,或者会阻止产生任何僵尸的东西。请帮忙。

【问题讨论】:

  • 正如我在对 Hoenir 回答的 mah 的评论中指出的那样,IMO 通常启动后台任务是错误的,您无法确定其结果(输出/成功/失败)或何时完成了,但我的回答说明了如何做,以防您对这种结构有合法用途。

标签: c linux exec fork zombie-process


【解决方案1】:

如果您想创建一个无需等待的“分离”进程,最好的方法是分叉两次,使其成为“孙子”进程。在直接子进程上立即waitpid,它应该在再次分叉后立即调用_exit(所以这个waitpid不会阻止父进程中的前进)。孙子进程将成为孤立进程,因此它会被 init 进程继承,您无需再次处理它。

或者,您可以使用SA_NOCLDWAITSIGCHLD 安装信号处理程序。然而,总的来说,这是一个非常糟糕的主意,因为它的影响是全球性的。它会严重破坏您使用的任何库代码需要能够等待子进程,包括标准库函数,如popen,可能是wordexp,可能是grantpt,等等。 p>

【讨论】:

    【解决方案2】:

    为了防止僵尸进程,您需要告诉父进程等待子进程,直到子进程终止。
    您需要使用库 'sys/wait.h' 中包含的 waitpid() 函数

    这里有一个示例代码,您可以使用 waitpid() 函数。

     #include <unistd.h>
        #include <sys/types.h>
        #include <errno.h>
        #include <stdio.h>
        #include <sys/wait.h>
        #include <stdlib.h>
    
    
    int main()
    {
        pid_t child_pid;
        int status;
        int local = 0;
        /* now create new process */
        child_pid = fork();
    
        if (child_pid >= 0) /* fork succeeded */
        {
            if (child_pid == 0) /* fork() returns 0 for the child process */
            {
                printf("child process!\n");
    
                // Increment the local and global variables
    
                printf("child PID =  %d, parent pid = %d\n", getpid(), getppid());
    
    
    
             }
             else /* parent process */
             {
                 printf("parent process!\n");
                 printf("parent PID =  %d, child pid = %d\n", getpid(), child_pid);
                 wait(&status); /* wait for child to exit, and store child's exit status */
           }
    
         //code ..
    

    【讨论】:

    • 仅仅等待一个子进程终止通常会破坏分叉到另一个进程的原因,所以没有一些添加(例如在@R的答案中发布),简单地说“调用wait()”不会似乎特别有帮助。
    • @mah: 公平地说,如果您要分叉一个进程来完成某项工作,您可能应该关心该工作的结果,因此有一些异步方法来确定它是否已完成(例如,在您的事件循环中读取 EOF 的管道)反过来告诉您何时为孩子waitpid。我认为创建一个真正分离的过程几乎总是错误的,但我的回答解决了如何正确地做到这一点,以防 OP 真的需要。
    【解决方案3】:

    @R:公平地说,有些用户可能会分叉一份工作,并且绝对不需要对生成的孩子的结果做出反应。 如果没有答案,任何对 wait() 函数的调用最终都可能会阻塞父进程,对吗?这可能会使飞机坠毁...

    【讨论】:

      【解决方案4】:

      你可以注册一个信号处理机制来防止子进程僵尸,

      这个 Link 将有助于解决您的问题。

      【讨论】:

      • (+1) 但始终包含解决方案的简短描述,以防万一将来链接不可用。
      猜你喜欢
      • 1970-01-01
      • 2013-06-05
      • 2016-03-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 2019-09-01
      • 2014-09-30
      • 1970-01-01
      相关资源
      最近更新 更多