在 Linux 系统中,僵尸进程(Zombie Process)是一种特殊的进程状态,虽然已经完成执行,但仍然保留在进程表中。本文将介绍僵尸进程的定义、危害、产生原因以及如何处理它们。
什么是僵尸进程?
僵尸进程是指已经完成执行(通过exit
系统调用、运行时发生致命错误或收到终止信号所致),但在操作系统的进程表中仍然存在其进程控制块(PCB)的进程。
尽管这些进程不再执行任何实际任务,但它们占据了一个位置,直到父进程调用wait()
或waitpid()
来获取其退出状态。
僵尸进程的危害
虽然僵尸进程不会占用 CPU 资源,但它们会占用系统内存和进程表中的位置,影响系统性能和稳定性。
如果系统中存在大量僵尸进程,可能导致进程表耗尽,从而无法创建新的进程。
僵尸进程产生的原因
1、父进程未回收子进程资源:
当父进程先于子进程结束,子进程成为孤儿进程。
孤儿进程会被 init 进程(进程号为 1)领养,并由 init 进程对其完成状态收集工作。
如果子进程先于父进程退出,同时父进程太忙无法回收子进程的资源,子进程的 PCB 存放于内核中,变成僵尸进程。
2、模拟僵尸进程的产生:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void) {
pid_t pid = fork();
if (pid == 0) {
printf("I am child, my parent=%d, going to sleep 3s\n", getppid());
sleep(3);
printf("-------------child die--------------\n");
} else if (pid > 0) {
printf("I am parent, pid=%d, my son=%d, going to sleep 5s\n", getpid(), pid);
sleep(5);
system("ps -o pid,ppid,state,tty,command");
} else {
perror("fork");
return 1;
}
return 0;
}
在这个程序中,父进程创建子进程后休眠 5 秒钟,子进程休眠 3 秒钟后退出。
如果父进程在子进程退出之前结束,子进程成为僵尸进程。
如何查看僵尸进程
用 ps 命令和 grep 命令查看僵尸进程:
ps -A -ostat,ppid,pid,command | grep -e '^[Zz]'
命令注解:
-A
:列出所有进程-o
: 自定义输出字段,设定显示字段为 stat(状态),ppid(父进程 pid),pid(进程 pid),command(命令行)这四个参数- 因为状态为
Z
或者z
的进程为僵尸进程,所以我们使用grep
抓取stat
状态为Zz
进程
运行结果如下所示:
Z 829377 829380 /command
如何杀死僵尸进程
对于普通进程,我们可以使用kill
命令来终止它们。
但对于僵尸进程,因为它们已经“死”过一次,无法再利用kill
命令杀死。
解决方法是杀死父进程,init 进程会领养僵尸进程并回收其资源。
例如,如果 PID 829380 是一个僵尸进程,其父进程是 PID 829377,可以使用kill
结束父进程(829377)来清理僵尸进程:kill -HUP 829377
总结
- 僵尸进程是 Linux 系统中的隐秘威胁,需要及时处理,以保持系统的健康运行。
- 父进程应该负责回收子进程的资源,避免产生僵尸进程。
- 使用合适的命令或方法来清理僵尸进程。