有什么办法可以让一个正在运行的进程处于D状态或者Z状态?

问题描述 投票:0回答:2

我目前正在针对某些故障注入测试我们的软件。现在我在 D 状态或 Z 状态下运行 systemd 守护进程时遇到问题。任何帮助将不胜感激!

linux process
2个回答
1
投票

创建“D”状态进程:

sudo cat $(mount | awk '$3 == "/" { print $1 }') > /dev/null
# Then run "top" command,
# Sometimes, you'll see "cat" process in "D" state, most of the time in "R" state

要创建“Z”状态进程,请使用以下 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;
}

然后

gcc -o zombie zombie.c
./zombie

0
投票

虽然另一个答案确实给出了创建D状态进程的方法,但它并不可靠,并且进程会重复进入和退出D状态。在 Linux 上,更可靠的方法是使用

vfork
(有关其工作原理的更多信息,请参阅本文)。举个例子:

#include <unistd.h>

__attribute__((noinline)) static void run_child(void)
{
    pause();
    _exit(0);
}

int main(void)
{
    pid_t pid = vfork();

    if (pid == 0) {
        run_child();
    } else if (pid < 0) {
        return 1;
    }

    return 0;
}

__attribute__((noinline))
是一个好主意,可以确保子级使用的堆栈空间与父级使用的堆栈空间分开。通过防止内联,我们确保函数在入口处创建一个不同的堆栈帧,并且在
vfork()e
d 子级的上下文中,这意味着任何堆栈操作都整齐地发生在单独的帧中,而不是在父级的堆栈帧中。如果没有它,编译器可能会执行优化,从而导致父级和子级之间的数据交错,这可能会导致父级恢复时堆栈损坏。

然后将进入 D 状态,直到发送终端信号:

% cc -o dstate dstate.c
% ./dstate & sleep 0.1; ps -o pid,state,cmd -p "$!"
[1] 780629
    PID S CMD
 780629 D ./dstate
% kill "$!"
[1]  + terminated  ./dstate

(Philippe 的另一个答案已经为 Z 状态过程提供了一个很好的解决方案,所以我将再次省略回答该部分。)

© www.soinside.com 2019 - 2024. All rights reserved.