进程等待-解决僵尸进程

为什么要进程等待

这又得说到僵尸进程了https://blog.csdn.net/cx2479750196/article/details/79963888
总结的来说,就是子进程退出,但是让子进程帮忙做事的父进程一直不查看子进程做事的结果,所以子进程进入僵尸状态,我们可以通过杀死父进程来退出此状态(但是很暴力),所以我们可以采取让父进程等待,让他记得要回收子进程资源,获取子进程的退出信息。

父进程是怎么等待的呢?

1、wait()方法

  #include<sys/types.h>
   #include<sys/wait.h>
   pid_t waitZ(int* status);

成功返回的是被等待进程的pid,失败返回-1
参数是输出型参数,获取子进程的状态,不关心状态时可以设置成NULL

2、waitpid()方法

pid_t waitpid(pid_t pid,int * status,int options);
正常返回子进程的id
参数pid:pid==-1,等待任意子进程,和wait一样
pid>0:等待其进程id与pid相等的子进程
status:
WIFEXITED(status):如果是正常终止子进程返回的状态,则为真
WEXITSTATUS(status):如果WIFEXITED非零,提取子进程退出码

具体思路:这里写图片描述
分析:两种方法都需要获取子进程status来作为返回值,如何获取返回值??

获取子进程status

status参数是由操作系统填充的,如果传递NULL,表示不关心状态,否则,操作系统会根据该参数将子进程的退出信息反馈给父进程。要将status看做成位图。
这里写图片描述

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int main(){
    pid_t pid=fork();
    if(pid<0){
        perror("fork()");
    }
    else if(pid==0){
        //child
        sleep(20);
        exit(10);//期望后面打印10

    }else{
        //father
        int st;
        int ret=wait(&st);//不关心子进程退出状态时wait(NULL);
        if(ret<0){
            printf("error");
        }
        else {
            if((st&0x7f)==0){//正常退出
                printf("exit code:%d\n",(st>>8)&0xff);
            }
            else{
                printf("sig code:%d\n",st&0x7f);
            }
        }
    }
}

这里写图片描述
父进程只能等待一个进程,如果wait与子进程个数不匹配,那么有的子进程就会陷入僵尸进程

  1 #include<unistd.h>
  2 #include<stdlib.h>
  3 #include<stdio.h>
  4 
  5 #include<sys/wait.h>
  6 int main(){
  7     printf("father:%d\n",getpid());
  8     pid_t id=fork();
  9     if(id==0){
 10         //第一个子进程
 11         printf("child:%d\n",getpid());
 12         sleep(3);
 13         exit(0);
 14     }
 15     //父进程
 16     id=fork();
 17     if(id==0){
 18     //第二个子进程
 19     printf("child:%d\n",getpid());
 20     sleep(5);
 21     exit(0);
 22     }
 23     wait(NULL);
 24    //   wait(NULL);
 25   //  printf("father do other thing");//只有一个wait()时就会有僵尸进程产生
 26     while(1){
 27         sleep(1);
 28         return 0;
 29     }
 30 }

演示waitpid方法:

2、waitpid()方法

pid_t waipid(pid_t pid,int* status,int options);
返回值:
正常返回返回的是子进程的id
参数pid:
pid==-1,等待任意子进程,和wait一样
pid>0:等待其进程id与pid相等的子进程status:
status:
WIFEXITED(status):如果是正常终止子进程返回的状态,则为真查看进程是否正常退出
WEXITSTATUS(status):如果WIFEXITED非零,提取子进程退出码查看退出码
options:
WNOHANG:如果pid指定子进程没有结束,则waitpid()返回0,不再等待,正常结束则返回子进程的id.

阻塞式等待:(父进程在等子进程子进程一天不结束父进程就无法往下执行)

   1 #include<sys/wait.h>
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<errno.h>
  6 int main(void){
  7 
  8     pid_t pid=fork();
  9     if(pid<0){
 10         perror("fork"),exit(1);
 11     }
 12    else if(pid==0){
 13         //child
 14         printf("child if run,pid:%d\n",getpid());
 15         sleep(5);//阻塞式等待。等待5s
 16         exit(257);
 17     }
 18     else{
 19         //father
 20         int st=0;
 21         pid_t ret=waitpid(-1,&st,0);//-1表示等待任意进程,正常返回子进程id,如果没有已退出的子进程返回0,调用出错返回-1.
 22         printf("this is test for wait\n");
 23         if(WIFEXITED(st)&&ret==pid){//WIFEXITED(st)在正常终止子进程的时候才为真。
 24         printf("wait child is sucess,child return %d\n",WIFEXITED(st));
 25         }else{
 26            printf("wait child failed");
 27            return 1;
 28         }
 29     }
 30     return 0;
 31 }

非阻塞时等待:

#include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/wait.h>
  5 int main(){
  6     pid_t pid=fork();
  7     if(pid<0){
  8         perror("fork()");
  9        return 1;
 10     }
 11     else if(pid==0){
 12         //child
 13         sleep(10);
 14         exit(10);  printf("child ifs run");
 15     }
 16     else{
 17         //father
 18         int st=0;
 19         int ret=0;
 20         do{
 21          ret=waitpid(-1,&st,WNOHANG);
 22         if(ret==0){//没有已退出的子进程可以收集
 23             printf("child is running\n");
 24         }
 25         sleep(1);
 26         }while(ret==0);//只要有子进程没有结束就要一次次进去查看状态
 27 
 28         if(WIFEXITED(st)&&ret==pid){//正常退出的状态下
 29                 printf("child exit code:%d\n",WEXITSTATUS(st));
 30             }
 31         else{
 32                 printf("wait failed\n");
 33                 return 1;
 34         }
 35     }
 36     return 0;
 37 }

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值