linux中wait与waitpid

进程

在linux中利用fork创建子进程,当子进程结束的时候,会产生僵尸进程,该僵尸进程会有保留一些内核的数据结构,供父进程查看子进程的状态;因此就有了wait与waitpid

wait(int *status)

用于父进程等待子进程,当子进程结束的时候,父进程才会被使用,相当于父进程被阻塞了;,同时其status用于父进程查询子进程当前是什么状态

wait获取staus后检测处理
宏定义  描述
WIFEXITED(status) 如果进程子进程正常结束,返回一个非零值
    WEXITSTATUS(status) 如果WIFEXITED非零,返回子进程退出码
WIFSIGNALED(status) 子进程因为捕获信号而终止,返回非零值
    WTERMSIG(status) 如果WIFSIGNALED非零,返回信号代码
WIFSTOPPED(status) 如果进程被暂停,返回一个非零值
    WSTOPSIG(status) 如果WIFSTOPPED非零,返回信号代码

waitpid(pid_t pid,int *status,int options)

用于等待指定的子进程,当子进程结束的时候,父进程才会被调用

  • pid > 0; 不用管其他子进程,只要该pid还没有结束,父进程就不会结束;
  • pid = -1; 等待任何一个子进程,此时waitpid和wait的作用一模一样
  • 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
  • pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
    options允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起
    返回值:成功返回等待子进程的pid,失败返回-1

wait使用

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main()
{
    int i = 0; 
    cout<<"before fork"<<endl;
    pid_t pid = fork();
    cout<<"after fork"<<endl;
    if(pid < 0)
    {
        cout<<"error"<<endl;
        return 1;
    }
    else if(pid == 0)
    {
        cout<<"fork sucess, this is son process"<<endl;
        while(i < 10)
        {
            i += 1;
            cout<<"this is son process, i = "<<i<<endl;
            sleep(1);
        }
    }
    else
    {
        int flag;
        pid_t p = wait(&flag); // 当子进程结束的时候,父进程才会调用,或者有信号来的时候父进程才会调用
        cout<<"fork sucess, this is father process, son process pid="<<pid<<endl;
        while(i < 10)
        {
            i += 2;
            cout<<"this is father process i="<<i<<endl;
            sleep(2);
        }
        i = WEXITSTATUS(flag); // 判断是否存在
        cout<<"i:"<<i<<"flag:"<<flag<<"p:"<<p<<endl;
    }
    cout<<"process destroy"<<endl;
    return 0;
}

运行结果, 等待父进程结束才运行

before fork
after fork
after fork
fork sucess, this is son process
this is son process, i = 1
this is son process, i = 2
this is son process, i = 3
this is son process, i = 4
this is son process, i = 5
this is son process, i = 6
this is son process, i = 7
this is son process, i = 8
this is son process, i = 9
this is son process, i = 10
process destroy
fork sucess, this is father process, son process pid=5170
this is father process i=2
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
i:0flag:0p:5170
process destroy

waitpid

先举个例子,当创建多个进程的时候,多个子进程与主进程同时运行

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
using namespace std;
pid_t create_fork()
{
    int i = 0;
    pid_t pid = fork();
    if(pid == 0) // 此时为子进程的内容
    {
        cout<<"fork sucess, this is son process, pid="<<getpid()<<endl;
        while(i < 2)
        {
            i += 1;
            cout<<"this is son process, i = "<<i<<" pid = "<<getpid()<<endl;
            sleep(1);
        }
        exit(1); // 子进程运行完之后直接结束
    }
    else if(pid > 0)
    {
        //wait(NULL); // 先结束子进程中的内容
        return pid;
    }
    else
    {
        perror("error");
    }
}
int main()
{
    pid_t p;
    for(int i = 0; i < 4; ++i)
    {
        create_fork();
    }
    int i = 0;
    while(i < 10)
    {
        i += 2;
        cout<<"this is father process i="<<i<<endl;
        sleep(2);
    }
    
    cout<<"process destroy"<<endl;
    return 0;
}

运行内容如下:

fork sucess, this is son process, pid=6662
this is son process, i = 1 pid = 6662
fork sucess, this is son process, pid=6663
this is son process, i = 1 pid = 6663
this is father process i=2
fork sucess, this is son process, pid=6664
this is son process, i = 1 pid = 6664
fork sucess, this is son process, pid=6665
this is son process, i = 1 pid = 6665
this is son process, i = 2 pid = 6662
this is son process, i = 2 pid = 6663
this is son process, i = 2 pid = 6664
this is son process, i = 2 pid = 6665
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
process destroy

此时没有使用waitpid,接下来修改相应的内容,当指定的子进程结束之后主进程才会运行。

修改每一个进程的睡眠时间,该内容让主进程保持第一个进程的pid,只有当第一个进程结束之后,主进程才会可以运行;

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
using namespace std;
pid_t create_fork(int time)
{
    int i = 0;
    pid_t pid = fork();
    if(pid == 0) // 此时为子进程的内容
    {
        cout<<"fork sucess, this is son process, pid="<<getpid()<<endl;
        while(i < 2)
        {
            i += 1;
            cout<<"this is son process, i = "<<i<<" pid = "<<getpid()<<endl;
            sleep(time);
        }
        cout<<"fork destroy pid = "<<getpid()<<endl;
        exit(1); // 子进程运行完之后直接结束
    }
    else if(pid > 0)
    {
        //wait(NULL); // 先结束子进程中的内容
        return pid;
    }
    else
    {
        perror("error");
    }
}
int main()
{
    pid_t p;
    for(int i = 0; i < 5; ++i)
    {
        pid_t temp = create_fork(i);
        if(i == 0)
        {
            p = temp;
        }
    }
    if(waitpid(p, NULL, 0))
    {
        int i = 0;
        while(i < 10)
        {
            i += 2;
            cout<<"this is father process i="<<i<<endl;
            sleep(2);
        }
    
    }
    cout<<"process destroy"<<endl;
    return 0;
}

结果如下,可以发现第一个经常destroy之后,主进程就开始了运行;

fork sucess, this is son process, pid=6769
this is son process, i = 1 pid = 6769
this is son process, i = 2 pid = 6769
fork destroy pid = 6769
fork sucess, this is son process, pid=6770
this is son process, i = 1 pid = 6770
fork sucess, this is son process, pid=6771
this is son process, i = 1 pid = 6771
this is father process i=2
fork sucess, this is son process, pid=6772
this is son process, i = 1 pid = 6772
fork sucess, this is son process, pid=6773
this is son process, i = 1 pid = 6773
this is son process, i = 2 pid = 6770
fork destroy pid = 6770
this is son process, i = 2 pid = 6771
this is father process i=4
this is son process, i = 2 pid = 6772
fork destroy pid = 6771
this is son process, i = 2 pid = 6773
this is father process i=6
fork destroy pid = 6772
this is father process i=8
fork destroy pid = 6773
this is father process i=10
process destroy

接下来修改代码,也就是说当最后一个进程执行完之后,主进程才会执行;

if(i == 4 ) // 将i 该为4
{
    p = temp;
}

运行结果如下

fork sucess, this is son process, pid=6823
this is son process, i = 1 pid = 6823
this is son process, i = 2 pid = 6823
fork destroy pid = 6823
fork sucess, this is son process, pid=6824
this is son process, i = 1 pid = 6824
fork sucess, this is son process, pid=6825
this is son process, i = 1 pid = 6825
fork sucess, this is son process, pid=6826
this is son process, i = 1 pid = 6826
fork sucess, this is son process, pid=6827
this is son process, i = 1 pid = 6827
this is son process, i = 2 pid = 6824
this is son process, i = 2 pid = 6825
fork destroy pid = 6824
this is son process, i = 2 pid = 6826
fork destroy pid = 6825
this is son process, i = 2 pid = 6827
fork destroy pid = 6826
fork destroy pid = 6827
this is father process i=2
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
process destroy

其中参数的使用

int temp1 = WIFEXITED(flag);
cout<<"WIFEXITED: 如果子进程正确结束返回一个非0值"<<temp1<<endl;
if(temp1 != 0)
{
    cout<<"如果子进程正常结束,返回子进程退出码"<<WEXITSTATUS(flag)<<endl;
}
if(WIFSIGNALED(flag) != 0)
{ // 不为0,表示因为捕获信号而终止
    cout<<"如果是因为捕获信号而终止的,返回相应的信号代码"<<WTERMSIG(flag)<<endl;
}
if(WIFSTOPPED(flag) != 0)
{
    // 如果进程被暂停,返回一个非0值
    cout<<"如果因为暂停,返回相应的信号代码"<<WSTOPSIG(flag)<<endl;
}

可以加长子进程的工作时间,利用正常结束进程或者是
kill -9 pid
杀死相应的子进程来查看状态

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值