【问题标题】:Can this C code create zombie processes?这个 C 代码可以创建僵尸进程吗?
【发布时间】:2014-01-03 03:06:04
【问题描述】:

我想知道下面的代码是否可以创建僵尸:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
    int i=1;
    pid_t p;
    p = fork();
    i++;
    if(p!=0){
        waitpid(p, NULL, 0);
    }
    printf("%d\n",i);
    return 0;
}

因此,父进程调用子进程的waitpid,如果子进程尚未退出,则立即返回。所以,到目前为止,还没有僵尸出现。但是,如果孩子在

之前退出
return 0;
命令这会是僵尸吗?我实际上对此感到困惑。 waitpid 是否应该是程序终止前的最后一行代码?任何帮助,将不胜感激。谢谢!

【问题讨论】:

  • 看起来不错,但您可能有误解。如果孩子已经死亡,waitpid 将立即返回;否则它将阻塞,直到孩子死去。除非您将 WNOHANG 与 waitpid 一起使用,否则它不会阻塞,但这不是问题。
  • 如果我错了,请纠正我,但我认为第三个参数(零)相当于WHOHANG。无论如何,让我们假设它是WHOHANG。然后会创建一个僵尸吗?如何创建?最后,waitpid 是否应该是 return 0 之前的最后一个命令?以确保不会创建僵尸?再次感谢!
  • No WNOHANG 绝对不等于 0。零是默认值,如果等于 0,则按位或 WNOHANG 没有意义。如果孩子在非阻塞 waitpid 后死亡并且父母先退出然后你会有一个僵尸。但通常您会在循环中使用非阻塞waitpid,并可能与接收 SIGCHLD 结合使用。 Waitpid 本身可以在代码中的任何位置,只要它在被调用时处理您的孩子。
  • 感谢您的回复!我还有一个问题:如果父进程在孩子死之前调用waitpid(p, NULL, WHOHANG);,那么孩子会变成僵尸,对吗?那么,在上面的代码中,是什么阻止了孩子在waitpid 的调用后死亡并因此成为僵尸?
  • 在上面的代码中,您没有使用 WNOHANG,因此有两种情况。 (1) 当waitpid 被调用并且waitpid 立即收获并返回时,孩子已经死了。 (2) 孩子还没有死,waitpid 阻塞等待孩子死亡。当它完成时,它会被收割并 waitpid 返回。希望对您有所帮助。

标签: c process pid zombie-process waitpid


【解决方案1】:

孩子只有在结束并且父母不打电话给wait*()时才会变成僵尸只要它自己还活着。

在父进程也结束的那一刻,子进程被init 进程收割,该进程会小心地在子进程上调用wait*(),因此它最终会结束并离开僵尸状态并从进程中消失列表。

为了让你的示例代码中创建的孩子变成僵尸,修改代码示例如下:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) 
{
    pid_t p = fork();

    if (p != 0) 
    {
        waitpid(p, NULL, 0); /* See if the child already had ended. */
        sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */
        pause(); /* Suspend main task. */
    }
    else
    {
        sleep(3); /* Just let the child live for some tme before becoming a zombie. */
    }

    return 0;
}

由于以下两个事实:

  • 孩子睡了 3 秒,所以父母对 waitpid() 的调用很可能总是失败
  • SIGCHLD 的默认处理是忽略它。

上面的代码其实是一样的:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void) 
{
    pid_t p = fork();

    if (p != 0) 
    {
        pause(); /* Suspend main task. */
    }
    else
    {
        sleep(3); /* Just let the child live for some tme before becoming a zombie. */
    }

    return 0;
}

【讨论】:

  • 这段代码中有什么可以防止孩子变成僵尸?你能更详细地解释一下你为什么使用睡眠和暂停命令吗?很抱歉有这么多问题,但我不熟悉这些概念。
  • @Konstantinos Konstantinidis:“这段代码中有什么可以防止孩子变成僵尸?”什么都没有。正如我的回答中所述,这段代码确实创建了一个僵尸。
【解决方案2】:

我找到了一种简单的方法来创建僵尸进程并使用 ps -e 对其进行测试

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void  main()
{
    pid_t pid;
    pid = fork();
    //parent sleeps while the child has exited
    //not an orphan since parent still alive
    //child will be still present in process table
    if(pid==0)
    {//child
        exit(0);
    }
    else
    {//parent
        sleep(15);
    }
}

在 15 秒内运行 ps -e... 你会看到

6454 pts/2 00:00:00 a.out

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 2021-12-09
    相关资源
    最近更新 更多