一、为啥要等待子进程退出
首先创建子进程的目的是为了让它干活,所以我们必须要收集子进程的退出状态,看它是不是正常退出还是异常退出;正常退出主要通过调用exit()函数退出,异常退出主要是调用abort函数或者是强行curl+C退出。
注意:当子进程的退出状态没有被获取的时候,此子进程被称为僵死进程zombie(僵尸进程)
二、怎么获取子进程的退出状态
wait()与waitpid()函数的原型
检查wait和waitpid所返回的终止状态的宏,若子进程是正常退出,则用WEXITSTATUS(status)来解析出子进程的返回状态值。
实验代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
int cet=0;
pid_t pid;
int stator;
pid=fork();
if(pid >0){
wait(&stator);
printf("stator=%d\n",WEXITSTATUS(stator));
while(1){
printf("This is fater program,fater pid=%d\n",getpid());
sleep(1);
printf("cet=%d\n",cet);
}
}
else if(pid == 0){
while(1){
printf("This is child program,child pid=%d\n",getpid());
sleep(1);
cet++;
if(cet == 3){
exit(3);
}
}
}
return 0;
}
实验结果:
以上结果可知调用wait()函数成功获取子进程退出的状态值。
三、wiatpid()函数的使用
waitpid()可以在获取子进程的状态时,不会对父进程进行堵塞,而且此时的子进程也被称为僵死进程zombie(僵尸进程)。
实验代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
int cet=0;
pid_t pid;
int stator=10;
pid=fork();
if(pid >0){
// wait(&stator);
waitpid(pid,&stator,WNOHANG);
printf("stator=%d\n",WEXITSTATUS(stator));
while(1){
printf("This is fater program,fater pid=%d\n",getpid());
sleep(1);
printf("cet=%d\n",cet);
}
}
else if(pid == 0){
while(1){
printf("This is child program,child pid=%d\n",getpid());
sleep(1);
cet++;
if(cet == 3){
exit(3);
}
}
}
return 0;
}
实验结果
实验表明当使用waitpid()来获取子进程的状态时,可以使用WNOHANG常量来使父进程不会被堵塞,但是这是的子进程也是僵死进程。
四、孤儿进程
父进程如果不等待子进程退出,在子进程结束之前就结束了自己的“生命”,此时子进程叫做孤儿进程;Linux避免系统存在过多孤儿进程,init进程会收留孤儿进程,变成孤儿进程的父进程。
实验代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int cet=0;
pid_t pid;
pid=fork();
if(pid >0){
printf("This is fater program,fater pid=%d\n",getpid());
}
else if(pid == 0){
while(1){
printf("This is child program,child pid=%d,fater pid=%d\n",getpid(),getppid());
sleep(1);
cet++;
if(cet == 10){
exit(3);
}
}
}
return 0;
}
由实验可知,当父进程还没结束时,子进程的父进程的PID等于当前的父进程PID,当父进程结束后,子进程还在运行时,Linux系统的init进程(PID=1)作为当前子进程的父进程。