一、wait 函数
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *wstatus);
功能:等待任意一个子进程结束,如果任意一个子进程结束了,该函数会回收子进程的资源。
参数:int *wstatus
进程退出时的状态信息,传入的是一个int类型的地址(用于接收进程退出时的状态信息),传出参数。
返回值:
- 成功:返回被回收的子进程的id
- 失败:-1 (所有的子进程都结束,调用函数失败)
调用wait函数的进程会被挂起(阻塞),直到它的一个子进程退出或者收到一个不能被忽略的信号时才被唤醒(相当于继续往下执行);如果没有子进程了,函数立刻返回,返回-1;如果子进程都已经结束了,也会立即返回,返回-1。
#include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { // 有一个父进程,创建5个子进程(兄弟) pid_t pid; // 创建5个子进程 for(int i = 0; i < 5; i++) { pid = fork(); if(pid == 0) { break; } } if(pid > 0) { // 父进程 while(1) { printf("parent, pid = %d\n", getpid()); // int ret = wait(NULL); int st; int ret = wait(&st); if(ret == -1) { break; } if(WIFEXITED(st)) { // 是不是正常退出 printf("退出的状态码:%d\n", WEXITSTATUS(st)); } if(WIFSIGNALED(st)) { // 是不是异常终止 printf("被哪个信号干掉了:%d\n", WTERMSIG(st)); } printf("child die, pid = %d\n", ret); sleep(1); } } else if (pid == 0){ // 子进程 while(1) { printf("child, pid = %d\n",getpid()); sleep(1); } exit(0); } return 0; // exit(0) }
二、waitpid 函数
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:回收指定进程号的子进程,可以设置是否阻塞。
参数:
- pid:
pid > 0 : 某个子进程的pid
pid = 0 : 回收当前进程组的所有子进程,一个进程组中可能包含多个进程
pid = -1 : 回收所有的子进程,相当于 wait() (最常用)
pid < -1 : 进程组的组 id 的绝对值,回收指定进程组中的所有子进程
- int *wstatus
进程退出时的状态信息,传入的是一个int类型的地址(用于接收进程退出时的状态信 息),传出参数
- options:设置阻塞或者非阻塞
0 : 阻塞
WNOHANG : 非阻塞
- 返回值:
> 0 : 返回子进程的id
= 0 : options=WNOHANG, 表示还有子进程活着
= -1 :错误,或者没有子进程了
#include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { // 有一个父进程,创建5个子进程(兄弟) pid_t pid; // 创建5个子进程 for(int i = 0; i < 5; i++) { pid = fork(); if(pid == 0) { break; } } if(pid > 0) { // 父进程 while(1) { printf("parent, pid = %d\n", getpid()); sleep(1); int st; // int ret = waitpid(-1, &st, 0); int ret = waitpid(-1, &st, WNOHANG); if(ret == -1) { break; } else if(ret == 0) { // 说明还有子进程存在 continue; } else if(ret > 0) { if(WIFEXITED(st)) { // 是不是正常退出 printf("退出的状态码:%d\n", WEXITSTATUS(st)); } if(WIFSIGNALED(st)) { // 是不是异常终止 printf("被哪个信号干掉了:%d\n", WTERMSIG(st)); } printf("child die, pid = %d\n", ret); } } } else if (pid == 0){ // 子进程 while(1) { printf("child, pid = %d\n",getpid()); sleep(1); } exit(0); } return 0; }