【问题标题】:How to create a zombie process that cannot be reaped for a few minutes如何创建几分钟无法收割的僵尸进程
【发布时间】:2014-11-02 23:57:47
【问题描述】:

有人可以建议我一种简单的方法来创建一个几分钟内无法收割的僵尸进程。 这样做的目的是测试父进程是否能够在僵尸进程再次变得可回收后对其进行回收。

可以在here 找到一个不可收割的僵尸案例。我想可能有更简单的方法来做到这一点。

操作系统:Linux

首选语言:C/C++

【问题讨论】:

  • 定义僵尸进程?否则你不妨做一个流程来做sleep(ETERNAL);
  • @Surt 我认为zombie-process 标签完美地定义了这些野兽:)
  • 在此处过度工程之前,您不能只启动一个线程然后不加入它吗?还是不算数?
  • @Surt 好吧,我想在不更改其代码的情况下测试父进程。它确实在等待孩子。
  • 投反对票的人会评论它的投票吗?因为我认为这个问题没有任何问题

标签: c++ c linux zombie-process


【解决方案1】:

这是一个小程序,它会导致僵尸出现在您的“ps aux”输出中几分钟。注意注释掉的 waitpid() 调用;如果取消注释该调用,僵尸将不会出现,因为 waitpid() 调用会导致父进程声明其死子。

(免责声明:我只在 MacOS/X 下进行了测试,因为这是我使用的计算机,但在 Linux 下应该可以正常工作)

#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
   printf("Starting Program!\n");

   int pid = fork();
   if (pid == 0)
   {
      printf("Child process %i is running!\n", getpid());
      sleep(300);  // wait 5 minutes
      printf("Child process %i is exiting!\n", getpid());
      return 0;
   }
   else if (pid > 0)
   {
      printf("Parent process is continuing child's pid is %i...\n", pid);
      sleep(5);  // just for clarity
      printf("Parent process is sending SIGKILL to child process...\n");
      if (kill(pid, SIGKILL) != 0) perror("kill");
      // waitpid(pid, NULL, 0);  // uncomment this to avoid zombie child process

      printf("Parent process is sleeping... ps aux should show process #%i is a zombie now\n", pid);
      sleep(500);  // just for clarity
      printf("Parent process is exiting!\n");
   }
   else perror("fork()");
}

【讨论】:

  • 感谢您的回答。尽管正如我提到的,我需要一个在一段时间内无法收割的僵尸。你得到僵尸是因为你没有收获它 - 这是一个不同的情况
【解决方案2】:

让我们从显而易见的开始 - 生命过程无法收获。让流程保持活力,仅此而已。

同样,您可以将进程嵌套在拒绝死亡的容器进程中,并且由于该容器进程是新的父进程,并且它没有进行任何收割或放弃对子进程的控制,因此没有人可以收割子进程(好吧……无论如何都是“孙子”)。

如果您希望操作系统避免占用您的进程,那么您在 macOS 上可能会很幸运(在 Big Sur 上测试过)。如果子进程被强制终止并且其父进程也被强制终止而没有收获子进程,MacOS 将忘记获取子进程。

该进程将显示为ps aux,但系统似乎从未获得崩溃的子进程,并且资源似乎仍在使用中(使用过的文件、打开的套接字、内存等)。

所以基本上你可以接受@jeremy-friesner 提供的答案并将其嵌套在一个进程中,你就完成了。

如果这些不是任何预期的效果,那么我可能误解了这个问题。

【讨论】:

  • MacOS 的行为似乎是一个严重的错误,或者您的测试有问题。收割孤儿僵尸是类 Unix 系统的一个非常基本的功能。在任何情况下,进程的内存、文件等都应该在它退出后立即释放,在它进入僵尸状态之前。
  • @NateEldredge - 我同意,但到目前为止,唯一的治疗方法是重新启动。老父母收到SIGCHLD,但从未收获,当它死亡时,进程所有权传递给PID 1(根),但由于某种原因它没有正确收获(我猜没有重复信号)。再说一次,我只在从终端运行代码(这意味着链中还有更多父级)然后引用终端时尝试过,所以问题可能隐藏在其他地方。当我的流程崩溃时……我做得很好,很好:)
  • 所以ps aux 显示孩子正在运行,PPID = 1,并且处于僵尸状态?
  • @NateEldredge ,ps aux 将孩子放在括号中(我认为这意味着它不再运行),PPID = 1,但它永远不会被收割(我认为这是因为信号孩子永远不会长大,为父亲处理的信号不会收割孩子)。我无法测试内核,但我可以破坏它(这不是很有趣,因为它需要我重新启动)。
  • 我不知道 MacOS ps 如何格式化它的输出,但是在我知道的 Unix 系统上,僵尸进程根本没有打印它的命令名称(你会得到类似 &lt;defunct&gt;反而)。括号更有可能表示“进程仍然存在但已换出”之类的意思。我会改为查看 STAT 列,Z 表示僵尸。
猜你喜欢
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多