关于进程等待
在子进程运行结束后,进入僵死状态,并释放资源,子进程在内核中的 数据结构 依然保留.
父进程调用wait()与waitpid()函数等待子进程退出后,释放子进程遗留的资源(task struct)
wait 与 waitpid
wait 函数
函数头文件
#include <sys/types.h>
#include <sys/wait.h>
函数原型
pid_t wait(int *wstatus ):
函数功能
让函数调用者进程进入到睡眠状态,等待子进程进入僵死状态后,释放相关资源并返回
函数参数
wstatus : 保存子进程退出状态值变量的指针获取具体值需要使用 WEXITSTATUS()宏定义
函数返回值
成功 : 返回退出子进程的 pid
失败 : 返回 -1
说明
会阻塞调用者进程(一般为父进程)
在子进程状态为僵死态时,回收资源,并释放资源后返回
示例:
创建一个子进程,延时35后退出,父进程等待子进程退出
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void){
pid_t cpid;
cpid = fork();
if (cpid == -1){
perror("[ERROR] fork():");
exit(EXIT FAILURE);
}
else if(cpid == 0){
printf("The Child process < %d > running...\n",getpid());sleep(3);exit(88);
}
else if(cpid > 0){
int rpid,status = 8;
rpid = wait(&status);
if (rpid == -1){
perror("[ERROR] wait() :");
exit(EXIT FAILURE);
}
printf("The Child Process < %d > has exited,exit code < %d>.\n",rpid,WEXITSTATUS(status));//通过 WEIXTSTATUS() 宏定义获取
}
return e;
}
在 wait 存储在 satus 变量的值,存储了很多信息,通过一系列 W 开头的宏来解析获取WIFEXITED(status): 进程是否正常结束
WEXITSTATUS(wstatus): 获取进程退出状态值,exit函数的参数
WIFSIGNALED(wstatus): 表示该子进程是否被信号结束的,返回真,则表示被信号结束的
WTERMSIG(wstatus): 返回结束该子进程的那个信号的信号值0
WCOREDUMP(wstatus): 表示该子进程被信号唤醒的
WIFSTOPPED(wstatus): 表示该子进程是否被信号中上(stop)的,返回真,则表示是被信号中止的
waitpid 函数
waitpid 函数的功能与 wait 函数一样,但比 wait() 函数功能更强大,可以理解成 wait() 底层调用waitpid()函数
函数头文件
#include <sys/types.h>
#include <sys/wait.h>
函数原型
pid t waitpid(pid t pid, int *wstatus, int options):
函数参数
pid:进程id
-1: 可以等待任意子进程
0 :等待 id 为 pid 的进程
wstatus : 保存子进程退出状态值变量的指针
options : 选项
WNOHANG : 非阻塞选项
函数返回值
成功:
0:退出进程的 pid
=0:在非阻塞模式下,没有进程退出
失败:
-1 并设置 errno
示例: 创建一个子进程,子进程运行后 3s 退出,进程等待子进程退出
总结
waitpid 函数常见用法如下:
使用阻塞的方式等待任意子进程退出
waitpid(-1,&status,0);
使用非阻塞的方式等待特定子进程退出
while(waitpid(pid,&status,WNOHANG) != 0)
usleep(50000)