创建僵尸进程

Posted

技术标签:

【中文标题】创建僵尸进程【英文标题】:Create zombie process 【发布时间】:2014-09-30 02:22:55 【问题描述】:

我有兴趣创建一个僵尸进程。据我了解,僵尸进程发生在父进程在子进程之前退出时。但是,我尝试使用以下代码重新:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main ()

  pid_t child_pid;

  child_pid = fork ();
  if (child_pid > 0) 
    exit(0);
  
  else 
    sleep(100);
    exit (0);
  
  return 0;

但是,此代码在预期执行后立即退出。但是,和我一样

ps aux | grep a.out

我发现 a.out 只是作为正常进程运行,而不是我预期的僵尸进程。

我使用的操作系统是 ubuntu 14.04 64 位

【问题讨论】:

您问题中的代码不会,因为在您的代码中,父进程首先退出,而子进程继续运行。 (请记住,fork() 在子进程中返回 0,在父进程中返回子进程的 PID。)要查看僵尸进程,您需要在父进程还活着但没有等待子进程时让子进程退出。如果您只是将代码的第 10 行从 if (child_pid &gt; 0) 更改为 if (child_pid == 0),它将“修复”您的代码,并且当子进程退出时您将能够看到僵尸进程。 【参考方案1】:

引用:

据我了解,僵尸进程发生在父进程在子进程之前退出时。

这是错误的。根据man 2 wait(见注释):

终止但没有等待的孩子变成了“僵尸”。

所以,如果你想创建一个僵尸进程,在fork(2)之后,子进程应该exit(),父进程在退出之前应该sleep(),让你有时间观察@的输出987654326@.

例如,您可以使用下面的代码代替您的代码,并使用ps(1)sleep()ing:

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

int main(void)

    pid_t pid;
    int status;

    if ((pid = fork()) < 0) 
        perror("fork");
        exit(1);
    

    /* Child */
    if (pid == 0)
        exit(0);

    /* Parent
     * Gives you time to observe the zombie using ps(1) ... */
    sleep(100);

    /* ... and after that, parent wait(2)s its child's
     * exit status, and prints a relevant message. */
    pid = wait(&status);
    if (WIFEXITED(status))
        fprintf(stderr, "\n\t[%d]\tProcess %d exited with status %d.\n",
                (int) getpid(), pid, WEXITSTATUS(status));

    return 0;

【讨论】:

非常感谢 chrk!我试过你的代码,我看到了一些僵尸进程。但我还有一个担忧。为什么我的代码没有创建僵尸进程?根据您帖子中的定义,子进程是否在没有被父进程等待的情况下退出(父进程已在没有等待命令的情况下退出)。 @chrk @user3354832 您在问题中的代码不会创建僵尸进程,因为在您的代码中,父进程首先退出,而子进程继续运行。 (请记住,fork() 在子进程中返回 0,在父进程中返回子进程的 PID。)要查看僵尸进程,您需要在父进程还活着但没有等待子进程时让子进程退出。如果您只是将代码的第 10 行从 if (child_pid &gt; 0) 更改为 if (child_pid == 0),它将“修复”您的代码,并且您将能够在子进程退出时看到僵尸进程。 只是为了详细说明。如果父级先退出,则子级现在是孤儿(其父级死亡),init 进程将采用它(因此新父级为 pid 1)。 init 进程注册了一个特殊的处理程序,以便在子进程死亡时收到通知,因此当子进程死亡时,它将等待它读取其状态码,因此子进程不会成为僵尸进程。如果 init 进程不这样做(例如在 docker 中运行时很常见),那么您的版本仍然会有僵尸。【参考方案2】:

Linux 中的僵尸或“失效进程”是指已经完成的进程,但由于父子进程之间缺乏对应关系,它的条目仍保留在进程表中。通常,父进程通过 wait() 函数检查其子进程的状态。当子进程完成时,等待函数向父进程发出信号以完全退出内存中的进程。但是,如果父进程未能为其任何子进程调用等待函数,则子进程在系统中仍作为死进程或僵尸进程保持活动状态。这些僵尸进程可能会在您的系统上大量堆积并影响其性能。

下面是一个在我们系统上创建僵尸进程的c程序将此文件保存为zombie.c:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main ()

  pid_t child_pid;

  child_pid = fork ();
  if (child_pid > 0) 
    sleep (60);
  
  else 
    exit (0);
  
  return 0;

通过此代码创建的僵尸进程将运行 60 秒。您可以通过在 sleep() 函数中指定时间(以秒为单位)来增加持续时间。

编译这个程序

gcc zombie.c

现在运行僵尸程序:

./a.out

ps 命令现在也会显示这个已失效的进程,打开一个新终端并使用以下命令检查已失效的进程:

aamir@aamir:~/process$ ps -ef | grep a.out
aamir    10171  3052  0 17:12 pts/0    00:00:00 ./a.out
aamir    10172 10171  0 17:12 pts/0    00:00:00 [a.out] <defunct> #Zombie process
aamir    10177  3096  0 17:12 pts/2    00:00:00 grep --color=auto a.out

【讨论】:

以上是关于创建僵尸进程的主要内容,如果未能解决你的问题,请参考以下文章

Linux僵尸进程详解

如何查找和杀掉Linux中的僵尸进程?

僵尸进程与孤儿进程

孤儿进程与僵尸进程

我正在尝试创建一个僵尸进程[重复]

Linux——进程概念进程创建僵尸进程孤儿进程环境变量程序地址空间详解