僵死进程,孤儿进程

一、孤儿进程

  1 #include<stdlib.h>
  2 #include<unistd.h>
  3 #include<stdio.h>
  4 int main()
  5 {
  6     int n=0;
  7     char *s = NULL;
  8     
  9     pid_t id = fork();
 10     if(id == -1)
 11     {
 12         exit(1);
 13     }
 14     if(id == 0)//在子进程中执行
 15     {
 16         n=3;
 17         s = "child";
 18     }
 19     else//在父进程中执行
 20     {
 21         n = 7;
 22         s = "parent";
 23     }
 24     
 25     int i =0;
 26     for(;i<n;i++)//父子进程都可以执行
 27     {
 28         printf("s =%s,curr_pid= %d,curr_ppid = %d\n",s,getpid(),getppid());
 29         sleep(3);
 30 
 31     }

父进程执行7次,子进程执行3次,运行结果如下:

如果我们将父进程改为执行3次,子进程执行7次

  1 #include<stdlib.h>
  2 #include<unistd.h>
  3 #include<stdio.h>
  4 int main()
  5 {
  6     int n=0;
  7     char *s = NULL;
  8 
  9     pid_t id = fork();
 10     if(id == -1)
 11     {
 12         exit(1);//0代表成功,1,2,3,,都是失败
 13     }
 14     if(id == 0)//在子进程中执行
 15     {
 16         n=7;
 17         s = "child";
 18     }
 19     else
 20     {
 21         n = 3;
 22         s = "parent";
 23     }
 24 
 25     int i =0;
 26     for(;i<n;i++)//父子进程都可以执行
 27     {
 28         printf("s =%s,curr_pid= %d,curr_ppid = %d\n",s,getpid(),getppid());
 29         sleep(3);
 30 
 31     }
 32 }

 父进程肯定先执行完,

结果如下:

 提示符出来的时候父进程执行完了,但子进程还没执行完。

因为运行的./main程序,也就是父进程,父进程执行完,命令提示符就会出现,等待下一个命令的输入,所以会出现上图情况,提示符出现了,子进程还没运行完,子进程继续输出。

上面运行程序时,父进程结束了,子进程还没结束,子进程就会变成孤儿进程。

孤儿进程会被一个固定的进程收养,一般是一号进程。

按约定,所以没有父进程的子进程都会被1号进程(也可以是其他进程,1号进程比较普遍)收养,1号进程成为子进程的父进程。

下图这个孤儿进程就是被1号进程收养

 下图这个孤儿进程就不是被一号进程收养,而是1477号进程

 1号进程就是系统启动后第一个创建出来的进程,init进程

二、进程结束过程

子进程结束后,exit (0)退出,占有的内存空间会被释放,进程实体会被删除,

exit (0); //退出码

0代表成功,其他数值代表不同类型的失败。

PCB中有专门的成员接收退出码  exit_code

系统要求父进程必须接收退出码,从而了解子进程的结束状态,成功还是失败。所以PCB在子进程运行结束时不会一起被删除,会保留到父进程获取了退出码才会被删除。

如果子进程结束前,父进程已经结束,子进程会被其他进程收养,这个进程会获取子进程的退出码。

三、僵死进程/僵尸进程

当子进程结束后,父进程还没有获取子进程的退出码,这时子进程被称为僵死进程/僵尸进程。此时的状态称为僵死状态。

若子进程还未结束,父进程已死亡,子进程会被1号进程 init 收养,再当子进程结束时时,init进程一定会获取子进程的退出码,子进程肯定不会变成僵死进程。

自己创建的进程可能会没有获取子进程的退出码,但init进程一定不会忘记获取。

  1 #include<stdlib.h>
  2 #include<unistd.h>
  3 #include<stdio.h>
  4 int main()
  5 {
  6     int n=0;
  7     char *s = NULL;
  8 
  9     pid_t id = fork();
 10     if(id == -1)
 11     {
 12         exit(1);//0代表成功,1,2,3,,都是失败
 13     }
 14     if(id == 0)//在子进程中执行
 15     {
 16         n=3;
 17         s = "child";
 18     }
 19     else
 20     {
 21         n = 7;
 22         s = "parent";
 23     }
 24 
 25     int i =0;
 26     for(;i<n;i++)//父子进程都可以执行
 27     {
 28         printf("s =%s,curr_pid= %d,curr_ppid = %d\n",s,getpid(),getppid());
 29         sleep(3);
 30 
 31     }
 32      exit(0);
 33 }

 四、僵死进程及处理方法

僵死进程:子进程先于父进程结束,父进程没有调用wait 获取子进程退出码。

如何处理僵死进程:父进程通过调用wait()完成。

进程正常结束(exit之后)才会获得退出码

调用wait,

通过此接口 WIFEXITED(wstatus)可以判断程序是否正常结束(正常结束指可以运行到exit,而不是中途崩掉)。正常结束返回true,

通过接口 WEXITSTATUS(wstatus)可以获得退出码

  1 #include<stdlib.h>
  2 #include<unistd.h>
  3 #include<stdio.h>
  4 #include<sys/wait.h>
  5 int main()
  6 {
  7     int n=0;
  8     char *s = NULL;
  9 
 10     pid_t id = fork();
 11     if(id == -1)
 12     {
 13         exit(1);//0代表成功,1,2,3,,都是失败
 14     }
 15     if(id == 0)//在子进程中执行
 16     {
 17         n=3;
 18         s = "child";
 19     }
 20     else
 21     {
 22         n = 7;
 23         s = "parent";
 24         int val = 0;//存储退出码
 25         int child_pid = wait(&val);//获取子进程的退出码
 26         if(WIFEXITED(val))//判断程序是否正常结束
 27         {
 28             printf("exit code :%d\n",WEXITSTATUS(val));//获得退出码
 29         }
 30     }
 31 
 32     int i =0;
 33     for(;i<n;i++)//父子进程都可以执行
 34     {
 35         printf("s =%s,curr_pid= %d,curr_ppid = %d\n",s,getpid(),getppid()    );
 36         sleep(3);
 37 
 38     }
 39     exit(3);//代表异常
 40 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值