“僵尸”进程是什么?通常情况下,僵尸进程的成因是因为该进程已经执行完毕,但是该进程的父进程却无法完整的将该进程结束掉(如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,即未接受其退出状态信息,那么它就一直保持僵尸状态),而造成该进程一直存在于内存中。
一个进程在调用exit命令结束自己的生命的时候,其实 它并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,它的作用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其完全销毁)所以僵尸进程需要父进程彻底结束他。
那么如何查看一个进程是否为僵尸进程呢?
ps:将某个时间点的进程运行状态选取下来
ps aux //查看系统所有的进程数据 -A:所有的进程均显示出来 -a:不与terminal有关的所有进程 -u:有效用户相关的进程 -x:通常与a一起使用,可以列出较完整的信息 -l:较长、较详细地将该PID的信息列出
当你获知它是一个僵尸进程后,那么你该如何干掉它呢,那么首先就得了解一下进程的管理。
程序之间的相互管理,是通过给予一个信号来进行管理的
查看信号(signal): 1、man 7 signal 2、kill -l
通常情况下,我们只需记住几个特别重要的信号即可。
1:启动被终止的进程,可让该PID重新读取自己的配置文件 9:强制中段一个进程,如果该进程运行到一半(如vim)会产生.filename.swap的半产品文件 15:正常结束一个进程 18:继续运行该进程 19:暂停一个进程kill -9 (+进程的pid)可以杀死这个进程
执行结果:43645成为僵尸进程
父进程循环创建子进程,子进程退出,造成多个僵尸进程。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 #include<errno.h> 5 6 7 void FunTest() 8 { 9 pid_t pid; 10 int n = 3; 11 while(n){ 12 n--; 13 pid = fork(); 14 15 if(pid < 0) 16 { 17 perror("fork error"); 18 exit(1); 19 } 20 else if(0 == pid) 21 { 22 printf("I am the child process.I am exiting\n"); 23 exit(0); 24 } 25 else{ 26 sleep(1); 27 continue; 28 } 29 30 } 31 printf("I am father process .I will sleep two second\n"); 32 sleep(2); 33 system("ps -o pid,ppid,state,tty,command"); 34 printf("father process is exting\n"); 35 36 } 37 38 int main() 39 { 40 FunTest(); 41 return 0; 42 }执行结果:43963 43964 43965三个僵尸进程
通过信号量机制
子进程退出时向父进程发出SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<errno.h> 4 #include<unistd.h> 5 #include<signal.h> 6 #include<sys/wait.h> 7 8 static void sig_child (int signo) 9 { 10 pid_t pid; 11 int status; 12 //deal Jiangshi process 13 while((pid == waitpid(-1,&status,WNOHANG)) > 0) 14 { 15 printf("child %d terminated\n",pid); 16 } 17 } 18 19 int main() 20 { 21 pid_t pid; 22 pid = fork(); 23 signal(SIGCHLD,sig_child); 24 if(pid < 0) 25 { 26 perror("fork error"); 27 exit(1); 28 } 29 else if(0 == pid) 30 { 31 printf("I am the child process. I am exiting\n"); 32 exit(0); 33 } 34 printf("I am the father process. I will sleep two seconds\n"); 35 sleep(2); 36 system("ps -o pid,ppid,state,tty,command"); 37 printf("father process is exiting\n"); 38 return 0;运行结果:僵尸进程被父进程成功回收。
一个父进程退出后,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 #include<errno.h> 5 6 int main() 7 { 8 int pid = fork(); 9 if(-1 == pid) 10 { 11 perror("fork error"); 12 } 13 else if(0 == pid) 14 { 15 printf("child is %d,father is %d\n",getpid(),getppid()); 16 sleep(2); 17 } 18 else{ 19 printf("father is %d,child is %d\n",getppid(),getpid()); 20 printf("father process is exuted\n"); 21 } 22 return 0; 23 }例如有个进程,它定期的产生一个子进程,这个子进程需要做的事情很少,做完它该做的事情之后就退出了,因此这个子进程的生命周期很短,但是,父进程只管生成新的子进程,至于子进程 退出之后的事情,则一概不闻不问,这样系统运行上一段时间之后,系统中就会存在很多的僵死进程。 倘若用ps命令查看的话,就会看到很多状态为Z的进程。 严格地来说,僵死进程并不是问题的根源,罪魁祸首是产生出大量僵死进程的那个父进程。 那我们该如何消灭系统中大量的僵死进程呢?答案就是把产生大量僵死进程的那个元凶杀掉(也就是通过kill发送SIGTERM或者SIGKILL信号啦)。杀掉元凶进程之后,它产生的僵死进程就变成了孤儿进程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程 就能瞑目而去了