waitpid函数的options参数
当options为0时,表示父进程为阻塞等待,阻塞等待是什么意思呢?
当options为WNOHANG(1)时,表示父进程为非阻塞等待,这又是什么意思?
WNOHANG:Linux底层就是C语言写的,而OS自己提供的接口函数,其实就是C语言函数,系统提供的一般大写的标记位WNOHANG,其实是宏定义!
WNOHANG——>wait no hang,一般别人说夯住了,其实就是这个进程没有被CPU调度(阻塞或者正等待调度),所以说,wait no 夯就是非阻塞等待。
阻塞等待就是,操作系统检测到子进程没有结束时,父进程就阻塞挂起,然后一直等到子进程运行结束父进程就被唤醒。
非阻塞等待就是,如果子进程没有退出,waitpid这个系统调用就会立马返回,而不用一直等待着子进程结束。
不妨看一下waitpid伪代码:
所以进程阻塞,本质还是在函数内部阻塞!
当父进程被唤醒的时候,还是从被挂起的地方开始执行。
那这个非阻塞等待有啥用呢,当父进程检测到子进程还在运行时,waitpid函数就会直接退出,父进程就可以去执行其他的任务,隔段时间再调用waitpid函数,只要子进程没结束父进程就去执行别的任务,只要子进程结束了父进程就可以释放掉僵尸进程,这就是基于非阻塞调用的轮询检测方案
代码示例:
#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
typedef void (*handler_t)();
std::vector<handler_t> handlers;
void fun_1()
{
printf("这是任务一\n");
}
void fun_2()
{
printf("这是任务二\n");
}
void Load()
{
handlers.push_back(fun_1);
handlers.push_back(fun_2);
}
int main()
{
pid_t id = fork();
if(id == 0)
{
int cnt=5;
while(cnt)
{
printf("我是子进程:cnt:%d pid:%d ppid%d\n",cnt--,getpid(),getppid());
sleep(1);
}
}
else
{
printf("我是父进程:pid:%d ppid:%d\n",getpid(),getppid());
int status = 0;
pid_t ret=waitpid(id,&status,WNOHANG);
int quit=0;
while(!quit)
{
ret=waitpid(id,&status,WNOHANG);
if(ret>0)
{
//等待成功,子进程退出
if(WIFEXITED(status))
{
printf("父进程等待子进程退出成功:退出码:%d\n",WEXITSTATUS(status));
}
quit=1;
}
else if(ret==0)
{
printf("子进程暂时还没有退出,父进程可以处理其他任务\n");
if(handlers.empty()){
Load();
}
int i=0;
for(i=0;i<handlers.size();i++)
{
handlers[i]();
}
}
else
{
printf("wait fail\n");
quit=1;
}
sleep(1);
}
}
return 0;
}