目录
- 一、什么是进程等待?
- 二、为什么要进行等待?
- 三、进程等待方法
- 1.wait函数
- 2.waitpid
- 3.status
- 阻塞等待和非阻塞等待(轮询等待)
- 1.阻塞等待
- 2.非阻塞等待
- 四、代码举例
一、什么是进程等待?
"进程等待"是指一个进程因为某些原因暂时无法继续执行,而必须等待某个条件满足或某个事件发生后才能继续执行的状态,是操作系统进行资源管理、任务调度和同步协调的重要机制之一。
通俗来讲就是我需要得到我想要的结果,我才能执行下一步
本文主要讲解父子进程之间的等待关系
二、为什么要进行等待?
首先我们要知道,在一个子进程退出时,父进程必须要回收子进程
即在子进程退出后,父进程需要知道交给子进程的任务是否完成,如果完成,是对了还是不对,如果没有完成,又是为什么,又是否正常退出
如果父进程没有回收好子进程的退出信息,子进程就会变成僵尸进程,从而导致内存泄漏问题
因此,父进程就会通过进程等待的方式,回收子进程资源,获取子进程的退出信息
三、进程等待方法
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:
- 用于保存子进程的退出状态。
注意:
- 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
- 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
- 如果不存在该子进程,则立即出错返回。
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;
}