子进程的回收:
#include<sys/wait.h>
pid_t wait(int *status)
功能:(阻塞函数)等待并回收任意子进程
参数:status 用于输出子进程的终止状态,可置NULL
返回值:成功返回所回收的子进程的PID,失败返回-1
父进程在创建若干自己进程以后调用wait函数:
A.若所有子进程都在进行,则阻塞,知道有子进程终止才返回
B.若有一个子进程已终止,则返回该子进程的PID并通过status参数输出其终止状态
C.若没有任何可被等待并回收的子进程,则返回-1,置erroe为ECHILD
wait函数主要完成三个任务
1.阻塞父进程的运行,直到子进程终止在继续,停等同步
2.获取子进程的PID和终止状态,令父进程得知谁因何而死
3.为子进程收尸,防止大量僵尸进程耗费系统资源
以上三个任务中,即使前两个与具体需求无关,仅仅第三个也足以
凸显wait哈桑农户的重要性,尤其是对那些多进程服务器型的应用而言
子进程的终止状态通过wait函数的status参数输出给该函数调用者。<sys/wait.h>头文件提供了
几个辅助分析进程终止状态的工具宏
WIFEXITED(status)
真:正常终止 WEXITSTATUS(status)->进程退出码
假:异常终止 WTERMSIG(status)->终止进程的信号
WIFSIGNALED(status)
真:异常终止 WTERMSIG(status)->终止进程的信号
假:正常终止 WEXITSTATUS(status)->进程退出码
#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid =fork();
if(pid == -1)
{
perror("fork");
return -1;
}
if(pid == 0)
{
printf("子进程%d\n",getpid());
//sleep(4);
//return 330;//正常终止
//exit(300);
//_exit(300);
//_EXIT(300);
abort();//异常终止
}
int status;//输出回收的子进程的终止状态
pid_t wait_pid = wait(&status);
if(wait_pid == -1)
{
perror("wait");
return -1;
}
printf("status = %d\n",status);
printf("父进程%d\n",getpid());
if(WIFEXITED(status))
{
printf("正常终止 退出码:%d\n",WEXITSTATUS(status));
}
else
{
printf("异常终止 信号:%d\n",WTERMSIG(status));
}
return 0;
}
子进程90815
status = 18944
父进程90814
正常终止 退出码:74
子进程90835
status = 6
父进程90834
异常终止 信号:6
//创建多个子进程 父进程回收
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>
int main()
{
//创建多个子进程
for(int i =0;i<5;i++)
{
pid_t pid = fork();
if(pid ==-1)
{
perror("fork");
return -1;
}
if(pid ==0)
{
printf("子进程:%d\n",getpid());
sleep(i+1);
return i;
}
}
//父进程回收多个子进程
while(1)
{
int status;
pid_t wait_pid =wait(&status);
if(wait_pid ==-1)
{
if(errno == ECHILD)
{
printf("没有子进程\n");
break;
}
else
{
perror("wait");
return -1;
}
}
printf("%d回收%d进程的僵尸\n",getpid(),wait_pid);
if(WIFEXITED(status))
{
printf("正常终止 退出码:%d\n",WEXITSTATUS(status));
}
else
{
printf("异常终止 信号:%d\n",WTERMSIG(status));
}
}
return 0;
}
子进程:90972
子进程:90971
子进程:90975
子进程:90973
子进程:90974
90970回收90971进程的僵尸
正常终止 退出码:0
90970回收90972进程的僵尸
正常终止 退出码:1
90970回收90973进程的僵尸
正常终止 退出码:2
90970回收90974进程的僵尸
正常终止 退出码:3
90970回收90975进程的僵尸
正常终止 退出码:4
没有子进程
//回收特定子进程
#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{
printf("父进程:%d\n",getpid());
int pid_arr[5] ={};
for(int i= 0;i < 5;i++)
{
pid_arr[i] = fork();
if(pid_arr[i] ==-1)
{
perror("fork");
return -1;
}
if(pid_arr[i] == 0)
{
printf("子进程:%d\n",getpid());
sleep(i+1);
return 0;
}
}
//父进程回收子进程
for(int i =4;i>=0;i--)
{
printf("我是%d父进程,我要回收%d子进程\n",getpid(),pid_arr[i]);
//阻塞方式回收子进程
pid_t wait_pid = waitpid(pid_arr[i],NULL,0);
if(wait_pid == -1)
{
perror("waitpid");
return -1;
}
printf("%d父进程回收%d子进程\n",getpid(),wait_pid);
}
return 0;
}
父进程:91906
子进程:91907
子进程:91908
子进程:91910
我是91906父进程,我要回收91911子进程
子进程:91909
子进程:91911
91906父进程回收91911子进程
我是91906父进程,我要回收91910子进程
91906父进程回收91910子进程
我是91906父进程,我要回收91909子进程
91906父进程回收91909子进程
我是91906父进程,我要回收91908子进程
91906父进程回收91908子进程
我是91906父进程,我要回收91907子进程
91906父进程回收91907子进程
//非阻塞方式回收子进程
#include<stdio.h>
#include<errno.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
pid_t pid = fork();
if(pid == -1)
{
perror("fork");
return -1;
}
if(pid == 0)
{
printf("子进程%d\n",getpid());
sleep(5);
return 0;
}
while(1)
{
pid_t pid = waitpid(-1,NULL,WNOHANG);
if(pid == -1)
{
if(errno == ECHILD)
{
printf("没有子进程了\n");
break;
}
else
{
perror("waitpid");
return -1;
}
}
else if(pid == 0)//非阻塞回收时,要回收的子进程在运行
{
printf("子进程正在运行,一会再来回收\n");
}
else
{
printf("回收了%d进程的僵尸\n",pid);
}
}
return 0;
}
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
回收了91875进程的僵尸
没有子进程了