关于僵尸进程和孤儿进程


tittle:关于僵尸进程和孤儿进程

进程的几种状态

  1. R状态 进程要么在运行要么在运行队列中。
  2. S状态 睡眠状态,进程在等待某事件完成(可被中断)
  3. D状态 不可中断的睡眠状态(通常其在第等待IO结的束)
  4. T状态 被停止的进程 (发送信号SIGSTOP停止进程 SIGCONT让进程继续运行)
  5. X状态 进程已死 已被回收 kernel你的do_exit函数返回的状态。
  6. Z状态 僵尸进程。。。

僵尸进程的产生

“僵尸”进程是什么?通常情况下,僵尸进程的成因是因为该进程已经执行完毕,但是该进程的父进程却无法完整的将该进程结束掉(如果他的父进程没安装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. 1:启动被终止的进程,可让该PID重新读取自己的配置文件
  2. 9:强制中段一个进程,如果该进程运行到一半(如vim)会产生.filename.swap的半产品文件
  3. 15:正常结束一个进程
  4. 18:继续运行该进程
  5. 19:暂停一个进程

kill -9 (+进程的pid)可以杀死这个进程

模拟一个僵尸进程

  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     pid = fork();
 11 
 12     if(pid < 0)
 13     {
 14         perror("fork error");
 15         exit(1);
 16     }
 17     else if(0 == pid)
 18     {
 19         printf("I am the child process.I am exiting\n");
 20         exit(0);
 21     }
 22     printf("I am father process.i will sleep two seconds\n");
 23     sleep(2);
 24     system("ps -o pid,ppid,state,tty,command");
 25     printf("father process is exiting\n");
 26 }
 27 
 28 int main()
 29 {
 30     FunTest();
 31     return 0;
 32 }

执行结果: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()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程 就能瞑目而去了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值