您的位置:首页 > 其它

关于僵尸进程和孤儿进程

2017-05-03 22:16 246 查看

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

进程的几种状态

R状态 进程要么在运行要么在运行队列中。

S状态 睡眠状态,进程在等待某事件完成(可被中断)

D状态 不可中断的睡眠状态(通常其在第等待IO结的束)

T状态 被停止的进程 (发送信号SIGSTOP停止进程 SIGCONT让进程继续运行)

X状态 进程已死 已被回收 kernel你的do_exit函数返回的状态。

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:启动被终止的进程,可让该PID重新读取自己的配置文件

9:强制中段一个进程,如果该进程运行到一半(如vim)会产生.filename.swap的半产品文件

15:正常结束一个进程

18:继续运行该进程

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()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程 就能瞑目而去了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: