【Linux】浅谈进程等待

15 篇文章 1 订阅

前言

前面我们说明了进程等待的必要性,父进程通过进程等待,来回收子进程的资源,并且得知子进程的运行状态,下面我们接着谈谈wait和waitpid


我们先看看wait和waitpid的函数声明

#include <sys/types.h>/* 提供类型pid_t的定义*/

#include <wait.h>

int wait(int *status)
#include<sys/types.h>
#include<sys/wait.h>
定义函数 pid_t waitpid(pid_t pid,int * status,int options);

这两个函数有相似的功能,我们以waitpid来举例说明

waitpid一共有三个参数

第一参数pid,它通常有两种赋值方式,-1,和pid > 0

-1就是等待该进程的任意一个子进程

> 0就是等待特定的进程,这个特定的进程也就是我们所要填入的pid值

第二个参数是status,它是一个输出型参数,主要是用来获取子进程的状态信息

如果子进程是正常跑完了它的代码,那么它的退出码是有意义的

如果子进程遇到了崩溃等其它情况,使它的代码没有跑完,那么它的退出码就没有意义,这时我们要看它的退出信号

上一篇文章已经说明过一种获取进程退出码和退出信号的方法了

接下来我们再说明另一种更加优雅的方式获取进程状态信息

使用两个宏函数来解决

WIFEXITED(status)

这个是用来检测子进程是否正常退出的,如果为true证明子进程是正常退出的,反之就没有正常退出

另一个宏函数是

WEXITSTATUS(status)

这个宏是用来获取子进程的退出码的

第三个参数options它也有两种赋值方式,0和WNOHANG

它默认是0,0代表着父进程阻塞式的等待子进程

换句话说是父进程不能再执行其它代码直到等待子进程退出

在操作系统上说是父进程被操作系统从运行队列上换下,放到阻塞队列或者等待被操作系统调度

这种方法是十分的不好的,创建子进程就没有什么意义了

另一种赋值方式就是WNOHANG这种方法就十分的好

它会检测子进程的退出状态,如果返回的是子进程的pid证明子进程已经退出

返回值是0证明子进程没有退出,还在运行

返回值是-1证明出错了

根据上面的解释也就是说,如果waitpid填入的是WNOHANG父进程调用一次检测一次子进程的状态,所以我们要不停的检测直到子进程退出或者其它情况。

在下一次调用waitpid的间隙,我们可以让父进程进行其他任务

下面有一个小例子

#include <iostream>
#include <vector>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

using namespace std;
    
    
typedef void (*handler_t)();    
    
std::vector<handler_t> handlers;    
    
void func_one()    
{    
    std::cout << "这是临时任务1" << std::endl;    
}    
    
void func_two()    
{    
    std::cout << "这是临时任务2" << std::endl;    
}    
    
void Load()    
{    
    handlers.push_back(func_one);    
    handlers.push_back(func_two);    
}    
    
int main()    
{    
    pid_t id = fork();    
                                                                                                                                                                                           
    if(id < 0)    
    {
        perror("fork");
        exit(1);    
    }   
    }
    else if(id == 0)
    {
        int cnt = 5;
        while(cnt--)
        {
            cout << "我是子进程" << cnt << getpid() << endl;
            sleep(1);
        }
    }                                                                                                                                                                                      
    else 
    {
        int status = 0;
        int quit = 0;
        cout << "我是父进程" << endl;
        while(!quit)
        {
            cout << "父进程等待子进程中" << endl;
            pid_t res = waitpid(-1, &status, WNOHANG); 
            if(res > 0)
            {
                cout << "等待子进程成功" << endl;
                cout << "子进程退出码为" << WEXITSTATUS(status) << endl;
                quit = 1;
            }
            else if(res == 0)
            {
                cout << "子进程还在运行" << endl;
                if(handlers.empty())
                {
                    Load();
                }

                for(auto iter : handlers)
                {
                    iter();
                }
            }
            else 
            {
                cout << "出错了" << endl;
                quit = 1;
                exit(1);
            }
            sleep(1);
        }
    }

    return 0;
}                                            


 

总结


以上就是今天要讲的内容,本文仅仅简单介绍了waitpid的使用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值