模拟实现——僵尸和孤儿进程

一 、僵尸进程

 1.   我们知道进程状态有:R运行状态,S睡眠状态(可中断睡眠状态),D磁盘休眠状态(不可中断睡眠状态),T停止状态,X死亡状态。还有一种比较特殊的就是僵尸状态(Z)了。

 2.    Z(zombie)--僵尸进程

    <1>当子进程退出,父进程无法读取到子进程退出的返回码时就会产生僵尸进程。父进程还在运行,子进程进入僵尸状态。

    <2>僵尸进程以进程中止的状态保持在进程表中,并且一直会等待父进程读取退出状态代码。

下面我们来实现一个简单的僵尸进程:

test.c代码部分:

1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 int main()
  5 {
  6     pid_t id=fork();
  7     if(id < 0){
  8         //error
  9         perror("fork");
 10         return 1;
 11     }
 12     else if( id == 0 ){//child
 13         printf("child[%d] is begin Z!!!\n",getpid());
 14         sleep(5);
 15         exit(EXIT_SUCCESS);
 16     }
 17     else{//parent
 18         printf("parent[%d] is sleeping!!!\n",getpid());
 19         sleep(30);
 20     }
 21 
 22     return 0;
 23 }

makefile:

  1 test:test.c                                                                                                                                              
  2     gcc -o test test.c
  3 
  4 .PHONY:clean
  5 clean:
  6     rm -f test

在此终端下编译代码:

编译时在另一个终端启动监控:

我们可以看到 ,子进程在睡眠后退出,由于父进程不读取其退出状态,子进程进入Z状态。

3.僵尸进程的危害

   <1>我们知道,父进程创建出子进程,是想让子进程完成某项工作,那么子进程退出时就要告诉父进程,你交给我的工作,我完成的如何。可是如果父进程一直不读取子进程的退出状态,那么子进程就会一直处于Z状态。因此,进程的退出状态必须被维持下去。

维护进程的退出状态本质上是要用数据维护,这个数据也属于进程信息,因此数据会保存在PCB中。如果Z状态一直不退出,那么PCB就要一直维护进程的退出状态。

如果一个进程创建出很多子进程,但它就是不读取子进程的退出状态,那么由于PCB占用内存,只开辟空间而不回收就会造成内存资源的浪费,进而造成内存泄漏。因此,父进程要及时回收子进程,避免内存泄漏,对系统造成威胁。

二、 孤儿进程

1.父进程先退出,子进程就被称为“孤儿进程”。

     父进程退出后,子进程被1号进程init领养,init进程对孤儿进程完成状态收集工作。

实现:

  1 #include<stdio.h>                                                                                                                                        
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 int main()
  6 {
  7     pid_t id =fork();
  8     if(id < 0){
  9         perror("fork");
 10         exit(0);
 11     }
 12     else if(id > 0){//parent
 13         printf("I am parent,pid:%d\n",getpid());
 14         sleep(5);
 15         exit(0);
 16     }
 17     else{//child
 18         printf("I am child,pid:%d\n",getpid());
 19         sleep(10);
 20         exit(0);
 21     }
 22     return 0;
 23 }

编译并且在另一个终端启动监控:

可以看出,当父进程退出后,子进程的ppid变为了1,这样,当一个孤儿进程结束了其生命周期的时候,init进程就会处理它的一切善后工作,因此一般来说,孤儿进程不会有什么危害。

猜你喜欢

转载自blog.csdn.net/a_struggling_monkey/article/details/83623454