自学内容网 自学内容网

【Linux操作系统】进程等待

一、什么是进程等待?

"进程等待"是指一个进程因为某些原因暂时无法继续执行,而必须等待某个条件满足或某个事件发生后才能继续执行的状态,是操作系统进行资源管理、任务调度和同步协调的重要机制之一。

通俗来讲就是我需要得到我想要的结果,我才能执行下一步

本文主要讲解父子进程之间的等待关系

二、为什么要进行等待?

首先我们要知道,在一个子进程退出时,父进程必须要回收子进程

即在子进程退出后,父进程需要知道交给子进程的任务是否完成,如果完成,是对了还是不对,如果没有完成,又是为什么,又是否正常退出

如果父进程没有回收好子进程的退出信息,子进程就会变成僵尸进程,从而导致内存泄漏问题

因此,父进程就会通过进程等待的方式,回收子进程资源,获取子进程的退出信息

三、进程等待方法

1.wait函数

#include<sys/types.h>
#include<sys/wait.h>

pid_t wait(int* status);

返回值: 成功返回被等待进程pid,失败返回-1。

status参数: 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

2.waitpid

#include<sys/types.h>
#include<sys/wait.h>

pid_ t waitpid(pid_t pid, int *status, int options);

返回值:

  • 成功时返回结束或暂停的子进程ID;

  • 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

  • 如果调用中出错,则返回-1,并设置errno来指示错误原因,这时errno会被设置成相应的值以指示错误所在

参数:

pid:

  • pid = -1:等待任意一个子进程。与wait等效。
  • pid > 0:等待其进程ID与pid相等的子进程。
  • pid = 0:等待与调用进程同组的任何子进程
  • pid < -1:等待进程组ID等于-pid的任何子进程。

options:

  • WNOHANG:如果指定的子进程没有结束,则waitpid立即返回0,而不是阻塞等待,若正常结束,则返回该子进程的ID。
  • WUNTRACED:如果子进程处于暂停状态(如由于接收到信号而暂停),则waitpid会返回该子进程的ID。

status:

  • 用于保存子进程的退出状态。

注意:

  1. 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  2. 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  3. 如果不存在该子进程,则立即出错返回。
    在这里插入图片描述

3.status

  • wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
  • 如果传递NULL,表示不关心子进程的退出状态信息,否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程

status 可以放回子进程的退出码和退出信号,是用来反馈子进程退出情况的

status不能简单的当作整形来看待,可以当作位图来看待,具体就涉及到进程信号的知识了

在这里插入图片描述

阻塞等待和非阻塞等待(轮询等待)

1.阻塞等待

阻塞等待很简单,也就是在没有得到你所等待的资源前,我就死板的一直等,等到海枯石烂

2.非阻塞等待

非阻塞等待又叫做轮询等待,即再等待某资源的同时还可以做其他事情

比如进程在等待某资源时,进程可以每过一段时间询问一下有没有资源,如果有就等待结束,如果没有就可以执行其他任务,然后过一段时间再次询问,然后往复循环这个过程

四、代码举例

1.阻塞等待

#include<iostream>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
using namespace std;

int main(int argc,char* argv[])
{
    pid_t pid = fork();
    if(pid==0)
    {
        cout<<"i am child process"<<endl;
        sleep(5);
        exit(100);
    }
    int status=0;
    //打印子进程的退出信号,coredump标志位,退出码
    pid_t wit =waitpid(pid,&status,0);
    if(wit==pid)
    {
        //子进程正常退出
        if(WIFEXITED(status))
        {
            //退出码
            cout<<"退出码:"<<WEXITSTATUS(status)<<endl;
            //退出信号
            cout<<"退出信号:"<<WTERMSIG(status)<<endl;
            //core dump信号,对于正常退出的进程,core dump 标志位总是 0
            cout<<"core dump:"<<WCOREDUMP(status)<<endl;
        }
        else
        {
            cout<<"fail"<<endl;
        }
    }

    return 0;
}

2.非阻塞等待

#include <stdio.h> 
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;

pid = fork();
if (pid < 0) {
printf("%s fork error\n", __FUNCTION__);
return 1;
}
else if (pid == 0) { //child
printf("child is run, pid is : %d\n", getpid());
sleep(5);
exit(1);
}
else {
int status = 0;
pid_t ret = 0;
do
{
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 child 5s success, child return code is :%d.\n", WEXITSTATUS(status));
}
else {
printf("wait child failed, return.\n");
return 1;
}
}
return 0;
}

原文地址:https://blog.csdn.net/liuty0125/article/details/142760071

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!