首先我们来看看什么是僵尸进程:
之前的学习过程中时这样理解僵尸进程的:子进程先于父进程退出,并将退出原因保留在pcb中,因此退出后不会自动释放所有资源,子进程退出后操作系统会通知父进程子进程退出了,你去获取一下原因,再完全释放子进程资源。若父进程不管子进程的退出状态,则该子进程为了保存退出原因而将进入僵死状态,成为僵尸进程。
而百度百科的解释为:在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。 但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程, 因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程, 看有没有哪个进程是刚刚结束的这个进程的子进程,如果是的话,就由Init 来接管他,成为他的父进程…
为了更好的理解,所以我写了一段代码
#include <stdio.h>
6 #include <unistd.h>
7 #include <errno.h>
8
9 int main()
10 {
11 int pid = fork();
12
13 if (pid < 0) {
14 //perror 是用于打印系统调用的错误原因
15 perror("fork error");
16 return -1;
17 }else if (pid == 0) {
18 printf("this is child!!\n");
19 }else {
20 printf("this is parent!!\n");
21 while(1){
22 sleep(1);
23 }
24 }
25
26 return 0;
27 }
~
由于父进程中有个死循环,所以父进程永远不会终止,按理来说此时由于父进程没有结束,所以子进程变为了一个僵尸进程。所以我赋值了另一个ssh渠道查看时果然有一个僵尸进程。(下图中第二行最后面的1 zombie表示:此时有一个僵尸进程)
上述查看系统中是否有僵尸进程,是通过top命令查看的(top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,常用于服务端性能分析。)
一般的发现僵尸进程后就需要将僵尸进程kill,因为僵尸进程会造成资源泄漏的问题。
此时,这个僵尸进程是我们自己写的,但是当不是我们自己产生僵尸进程,该如何找到这个僵尸进程呢?
那么就要通过命令 ps -aux | grep Z 来查找这个僵尸进程。
此时可以看到<defunc>结尾的就是我们要找的,从中可以看到该僵尸进程的PID为8558,所以我们就可以用命令kill -9 8809来kill这个僵尸进程。
但是有的情况下时直接kill不了僵尸进程的,所以要通过kill其父进程的方法来间接的kill僵尸进程;
此时可以通过命名cat /proc/8809/status 查看该僵尸进程的信息。
可以看到僵尸进程的PID为8809;该僵尸进程的父进程的PID(即此处的PPID)为8808;所以此时用kill -9 8808就能将父进程Kill掉,与此同时也将僵尸进程kill掉了;在用top查看时,已经没有僵尸进程了;
至此,将一个僵尸进程找到并且kill,避免了僵尸进程造成的资源泄露的危害
再把其中的这几个命令归纳如下:
查看系统中是否有僵尸进程: top
查找该僵尸进程:ps -aux|grep Z // 以<defunct>结尾的就是僵尸进程,此时也可看到僵尸进程的PID
根据僵尸进程的PID查看僵尸进程的详细信息:cat /proc/僵尸进程的PID/status
kill一个进程:kill -9 进程的PID