进程的等待

发布时间 2023-04-01 13:51:51作者: shubin

关于进程等待

在子进程运行结束后,进入僵死状态,并释放资源,子进程在内核中的 数据结构 依然保留.
父进程调用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)