僵尸进程和孤儿进程

1.进程创建

会用到的函数:
getpid() 获取进程的PID,谁调用则获取谁的
getppid() 获取父进的PID
fork() 用来创建一个子进程(父子进程为相互独立的进程),返回值pid_t (其实就是int被typedef为pid_t),无参,属于系统调用函数。这个函数的返回值会比较特殊,返回值有两个,分两类进行说明:
(1)创建成功则返回一个小于0的数(-1)
(2)创建失败会分别给父进程和子进程一个返回值,父进程得到的返回值为大于0的数(创建出来的子进程的PID) ,返回给子进程的是0。

fork()函数创建子进程的原理:fork会将父进程的PCB拷贝一份给子进程(但是父子进程为相互独立的进程);父进程中会保存子进程的PID,子进程会保存父进程的PID,这样父子进程就能联系在一起了;
比如创建了下面这样一个父子进程,来看看程序是怎么运行的:

 #include <stdio.h>                                                                           
 #include <stdlib.h>    
   int main() {    
   pid_t id = fork();    
     if(id < 0){ perror("fork");    
       return 1;    
       }    
     else if(id > 0){    
       //parent    
     printf("parent[%d] is sleeping...\n", getpid());    
    sleep(30);    
     }    
     else{    
   		 printf("child[%d] is begin Z...\n", getpid());    
    	 sleep(5);    
         exit(EXIT_SUCCESS);    
     }    
     return 0;    
   }   

子进程会拷贝父进程的PCB,父子进程拥有相同的代码段,但是由于fork()的返回值不同,父子进程执行的代码块不同。
在这里插入图片描述
问题1:子进程是从fork()开始运行的,还是从foork()之后开始运行的?
fork()之后,因为父进程在执行完毕fork之后,程序计数器当中保存的是fork之后的指令,子进程拷贝父进程的PCB,也将程序计数器信息拷贝了,所以是从fork之后开始执行
问题2:父进程先执行还是子进程先执行?
父进程先运行
问题3:创建出子进程之后父子进程谁先执行?
不确定,父子进程是抢占式执行的(CUP少,进程多,并发执行)。

有了上面这些基础,来开始学习一下如何创建和杀死僵尸进程。

2.僵尸进程

僵尸状态:Z 僵死状态(Zombies)是一个比较特殊的状态,进程退出,但是资源没有被完全释放的一种等待处理状态。
产生原因:当子进程退出并且父进程没有读取到子进程退出的返回代码(子进程退出原因)时就会产生僵死(尸)进程。僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
僵尸进程的危害:子进程占用了操作系统的资源(PCB需要维护它一直保存着它的信息),造成内存泄漏。每个用户有最大进程数量限制。

模拟僵尸状态:子进程退出+父进程进入死循环。

#include <stdio.h>                                                                              
#include <sys/types.h>    
#include <unistd.h>    
int main()    
{    
  pid_t ret = fork();    
  if(ret<0){    
    printf("ret:%d\n",ret);    
    return -1;    
  }    
  else if(ret ==0){    
    //child    
    printf("父进程:I :%d\n",getpid());    
    printf("father :%d\n",getppid());    
    sleep(30);    
    
  }    
  else{    
    //father    
    while(1){    
      sleep(1);    
      printf("子进程:I :%d\n",getpid());    
      printf("father :%d\n",getppid());    
    } 

执行程序可以看到以下信息:
在这里插入图片描述

如何杀死僵尸进程:
1.重启操作系统 ,虽然可以,但显然不是首选
2.杀掉父进程,这样子进程就会被1号进程领养,1号进程会回收该子进程的资源:
如何杀死一个进程:找到进程的PID,然后使用kill命令
kill [PID] 杀死一个进程
kill -9 [PID] 强杀一个进程
3.进程等待,使用wait(),waitpid()函数等待子进程的退出。

3.孤儿进程

父进程先于子进程退出,子进程就成了孤儿进程,会被1号进程所领养,
注意:没有孤儿状态

为了看到现象,将子进程设为死循环,父进程在30S后结束,上面代码稍微改一下就成了

#include <stdio.h>                                                                              
#include <sys/types.h>                           
#include <unistd.h>                              
int main()                                       
{                                                
  pid_t ret = fork();                            
  if(ret<0){                                     
    printf("ret:%d\n",ret);                      
    return -1;                                   
  }                                              
  else if(ret ==0){                              
    //child                                      
    while(1){                                    
      sleep(1);                                  
      printf("子进程:I :%d\n",getpid());        
      printf("father :%d\n",getppid());          
    }                                            
  }                                              
  else{                                          
    //father                                     
    printf("父进程:I :%d\n",getpid());          
    printf("father :%d\n",getppid());            
    sleep(30);                                   
  }          

在这里插入图片描述

杀死孤儿进程就比较简单了: kill [PID] 杀死一个进程
kill -9 [PID] 强杀一个进程

孤儿进程特点:脱离终端,运行在后台;父进程成为1号进程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值