子进程无论是正常或异常退出,内核都会向父进程发送信号 SIGCHILD.,因为无论是使用wait函数(阻塞),还是使用waitpid(得循环判断)都会将父进程阻塞住,而不能执行别的操作,所以,如果父进程还需要执行别的操作,就将wait/waitpid函数置于信号捕捉函数中就可以解决这个问题了,(当然也可以在父进程中单独起个线程来解决。)
wait函数、waitpid函数每次都只能回收一个子进程。
参考该文。
wait函数是通过waitpid函数封装的:
static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}
1、区别1:返回值的区别
wait函数只有两个返回值,
成功返回回收的子进程id;
失败返回-1,errno被置为ECHILD。(调用进程没有子进程,调用就会失败,wait函数用这个条件来判断是否还有子进程没有回收),
waitpid函数的第三个参数设置为WNOHANG 时,返回值相较wait多了一种返回值,waitpid发现当前进程在运行,没有已退出的子进程可收集,则立即返回,返回值为0();当所有的子进程都已回收,则返回-1.(这一点与wait是一样的,同样可以根据这个参数来判断是否还有子进程没回收)
2、区别2:
wait函数会阻塞等待子进程的退出。
waitpid函数,当第三个参数使用WNOHANG时,无子进程退出,也会立刻返回(返回值为0)
3、回收多个子进程
使用waitpid来循环回收子进程(不需要知道子进程的数量)
方法一:使用信号,在捕捉函数中调用waitpid
此处使用了信号的形式来:else if (pid > 0) {Close(connfd);signal(SIGCHLD,wait_child);} main函数外定义回调函数void wait_child(int signo)
{while(watipid(0,NULL,WNOHANG)>0); //大于0则继续回收return;
}
方法二:直接在父进程中调用waitpid,参考该文。
while(1) /*无限循环保证所有子进程全部回收*/{pid_t wpid = waitpid(-1/*回收任何子进程*/, NULL, WNOHANG);if(wpid == -1){break; /*如果返回-1说明已经没有子进程了,退出循环*/}if(wpid > 0){printf("wpid: %d\n", wpid); /*打印被回收的子进程的ID*/}}//while循环中,没有使用sleep函数,也就是说,没有进程可回收,就立马返回。//这个函数,其实还可以再加一句,
if(wpid==0)continue;
使用wait函数来循环回收子进程(wait函数是阻塞进程的),参考该文
使用wait()回收多个子进程
首先使用wait()函数来回收多个子进程,我们可以在一个for循环中等待子进程的结束,创建了几个子进程就for循环等待几次,代码如下
/************************************************************>File Name : mutipwait.c>Author : Mindtechnist>Company : Mindtechnist>Create Time: 2022年05月20日 星期五 17时23分57秒
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main(int argc, char* argv[])
{int i = 0;pid_t pid;for(i = 0; i < 5; i++){pid = fork();if(pid == 0){printf("child: %d\n", getpid());break;}}sleep(i);if(i == 5) /*只有父进程可以执行到i=5*/{for(i = 0; i < 5; i++){pid_t wpid = wait(NULL);printf("wpid: %d\n", wpid);}while(1){sleep(1);}}return 0;
}
//使用wait函数循环回收子进程是否也可以向waitpid一样,可以不知道进程个数呢?
这个待测试while(wait(NULL)>0);