僵尸进程产生方法

jydfmetal 旅游 5

僵尸进程的产生方法

僵尸进程(Zombie Process)是指子进程已经终止,但其退出状态未被父进程回收(通过 wait()waitpid() 系统调用),导致该进程的进程描述符仍然保留在系统中。以下是常见的僵尸进程产生方法:

父进程未调用 wait()waitpid()

子进程结束后,父进程如果没有调用 wait()waitpid() 回收子进程的状态信息,该子进程就会变成僵尸进程。

#include <stdio.h>
#include <unistd.h>

int main() {
pid_t pid = fork();
if (pid == 0) {
printf("Child process exiting\n");
return 0;  // 子进程退出
} else {
printf("Parent process running\n");
sleep(30);  // 父进程不回收子进程
}
return 0;
}

父进程被信号中断

如果父进程被某个信号(如 SIGKILL)中断,导致无法正常执行 wait(),其子进程可能会变成僵尸进程。

父进程未处理 SIGCHLD 信号

默认情况下,父进程会忽略 SIGCHLD 信号,但如果父进程显式设置了 SIG_IGN,系统会自动回收子进程,不会产生僵尸进程。相反,如果父进程没有正确处理 SIGCHLD,子进程可能会滞留。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main() {
signal(SIGCHLD, SIG_IGN);  // 忽略 SIGCHLD,不会产生僵尸进程
pid_t pid = fork();
if (pid == 0) {
printf("Child process exiting\n");
return 0;
} else {
printf("Parent process running\n");
sleep(30);
}
return 0;
}

父进程持续运行但不回收子进程

某些情况下,父进程可能长期运行但不主动回收子进程,导致系统中积累大量僵尸进程。

#include <stdio.h>
#include <unistd.h>

int main() {
for (int i = 0; i < 5; i++) {
pid_t pid = fork();
if (pid == 0) {
printf("Child %d exiting\n", i);
return 0;
}
}
printf("Parent process running\n");
sleep(60);  // 不回收任何子进程
return 0;
}

僵尸进程的查看方法

可以通过 ps 命令查看系统中的僵尸进程:

ps aux | grep 'Z'

输出示例:

USER PID STAT COMMAND
root 1234 Z [child]

其中 STAT 列显示 Z 表示僵尸进程。

如何避免僵尸进程

  • 父进程主动调用 wait()waitpid() 回收子进程。
  • 父进程设置 SIGCHLD 信号处理函数为 SIG_IGN,让系统自动回收子进程。
  • 使用双 fork 技巧,让子进程被 init 进程接管(PID=1)。
#include <stdio.h>
#include <unistd.h>

int main() {
pid_t pid = fork();
if (pid == 0) {
pid_t grandchild = fork();
if (grandchild == 0) {
printf("Grandchild process running\n");
sleep(5);
printf("Grandchild exiting\n");
return 0;
} else {
printf("Child process exiting\n");
return 0;  // 子进程退出,孙子进程由 init 接管
}
} else {
wait(NULL);  // 父进程回收子进程
printf("Parent process done\n");
}
return 0;
}

通过以上方法,可以有效模拟僵尸进程的产生,并了解如何避免它们。

抱歉,评论功能暂时关闭!