子进程退出,父进程为什么要等待?

在模拟实现之前,我们首先要理解什么是阻塞状态?
操作系统将不满足某种条件的进程从运行队列中拿出,将其状态设置为其他状态并放入等待队列中,在此等待队列中的进程的都处于阻塞状态。

一、父进程为什么要等待?

1、僵尸进程,造成内存泄漏
2、父进程得管理子进程,所以父进程派给子进程的任务完成的如何,我们都需要知道,如,子进程运行完成,运行结果对还是不对,或者是否正常退出
3、父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

二、等待的方法

  • wait方法
    pid_t wait(int *status);
    返回值:成功返回被等待进程的pid,失败返回-1
    参数:输出型参数,获取子进程状态,不关心则可设置为NULL
  • waitpid方法
    pid_t waitpid(pid_t pid, int *status, int options);
    返回值:
    正常返回的时候waitpid返回收集到的子进程的ID;
    如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在。
    参数:
    pid:
    pid=-1,等待任意一个子进程,与wait等效
    pid>0,等待其进程ID与pid相等的子进程
    status:
    WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
    WEXITSTATUS(status):若WIFEXITED非0,提取子进程退出码。(查看进程的退出码)
    options:
    0:阻塞式等待
    WNOHANG(非阻塞式等待):若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID。
    注意:
  • 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息
  • 如果在子进程存在且正常运行时调用,则进程可能阻塞
  • 如果不存在该子进程,则立即出错返回

三、模拟实现

  • 进程的阻塞等待方式
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <error.h>
int main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
    {
        perror("fork error\n");
        return 1;
    }
    else if(pid == 0)
    {
        //child
        printf("child is run,pid is :%d\n",getpid());
        sleep(5);
        exit(210);
    }
    else
    {
        //parents
        int status = 0;
        //阻塞式等待任意一个子进程
        pid_t ret = waitpid(-1, &status, 0);
        printf("wait...\n");
        if(WIFEXITED(status) && ret == pid)
        {
            //等成功,提取出退出码
            printf("wait success, child return code is :%d.\n", WEXITSTATUS(status));
        }
        else
        {
            printf("wait failed...\n");
            return 1;
        }
    }
    return 0;
}

输出结果:
在这里插入图片描述
子进程未退出之前,父进程啥都不干,一直在等待,5秒后子进程退出,才提取出退出码。

  • 进程的非阻塞等待方式
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <error.h>
int main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
    {
        perror("fork error\n");
        return 1;
    }
    else if(pid == 0)
    {
        //child
        printf("child is run,pid is :%d\n",getpid());
        sleep(5);
        exit(1);
    }
    else
    {
        //parents
        int status = 0;
        pid_t ret = 0;
        do
        {
            //非阻塞式等待,没有已退出的子进程,返回值是0
            ret = waitpid(-1, &status, WNOHANG);
            if(ret == 0)
            {
                printf("child is running...\n");
            }
            sleep(1);
        }while(ret == 0);
        if(WIFEXITED(status) && ret == pid)
        {
            //等成功,提取出退出码
            printf("wait success, child return code is :%d.\n", WEXITSTATUS(status));
        }
        else
        {
            printf("wait failed...\n");
            return 1;
        }
    }
    return 0;
}

输出结果:
在这里插入图片描述
子进程没有退出,父进程每隔1秒去检测一次,若没有检测到已退出的子进程,就立即退出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值