孤儿进程:
概念:若子进程的父进程已经死掉,而子进程还存活着,这个进程就成了孤儿进程。
为了保证每个进程都有一个父进程,孤儿进程会被init进程领养,init进程成为了孤儿进程的养父进程,当孤儿进程退出之后,由init进程完成对孤儿进程的回收。init进程的pid=1。
僵尸进程:
概念:子进程先退出,父进程没有完成对子进程资源的回收(父进程还没结束),此时子进程就变成了僵尸进程。
如何解决:
不能使用kill -9直接杀死僵尸进程,原因是僵尸进程是一个死掉的进程。
应该使用杀死僵尸进程父进程的方法来解决僵死进程;
原因是:杀死其父进程可以让init进程领养僵尸进程,最后由init进程回收僵尸进程(init进程回收已经结束的进程)。
wait函数:
函数原型: pid_t wait(int *wstatus);
函数作用:
- 阻塞并等待子进程退出。
- 回收子进程残留资源。
- 获取子进程结束状态(退出原因)
返回值:
- 成功:清理掉的子进程的pid
- 失败:-1(没有子进程)
wstatus参数:
1 WIFEXITED(wstatus):为非零->进程正常结束
WEXITSTATUS(wstatus):获取进程退出状态(return ...)
2 WIFSIGNALED(wstatus):为非零->进程异常结束(被信号杀死)
WTERMSIG(wstatus):取得进程终止的信号编号

结果:

waitpid函数:
函数原型: pid_t waitpid(pid_t pid, int *wstatus, int options);
函数参数:
pid:
< -1   meaning  wait  for  any  child process whose process group ID isequal to the absolute value of pid.-1     meaning wait for any child process.0      meaning wait for any child process whose  process  group  ID  isequal  to that of the calling process at the time of the call towaitpid().> 0    meaning wait for the child whose process  ID  is  equal  to  thevalue of pid.
pid=-1 等待任一子进程。与wait等效。
pid>0 等待其进程id与pid相等的子进程。
options:设置为WNOHANG,函数为非阻塞,设置为0,函数阻塞。(阻塞的话父进程执行不了剩余的代码,除非子进程全部回收)
函数返回值:
>0:返回回收掉的子进程id
=-1:无子进程
=0:参数三为WNOHANG,且子进程正在运行。
使用:
  1 #include<stdio.h>2 #include<stdlib.h>3 #include<string.h>4 #include<sys/types.h>5 #include<unistd.h>6 #include <sys/wait.h>7 int main()8 {9     //pid_t fork(void);10     pid_t pid=fork();11     if(pid<0)12     {13         perror("fork error");14         return -1;15     }16     else if(pid==0)17     {18         printf("child:pid==[%d],fpid=[%d]\n",getpid(),getppid());19         sleep(1);20         return 33;21     }22     else if(pid>0)23     {24         printf("father:pid==[%d],fpid=[%d]\n",getpid(),getppid());25         // pid_t wait(int *wstatus);26         int wstatus;27         // pid_t waitpid(pid_t pid, int *wstatus, int options);28         while(1)29         {30             pid_t wpid=waitpid(-1,&wstatus,WNOHANG);31             if(wpid>0)32             {33                 printf("child:[%d] terminated\n",wpid);34                 if( WIFEXITED(wstatus))35                 {36                     printf("child normal exit,wstatus=[%d]\n",WEXITSTATUS(wstatus));37 38                 }39                 else if( WIFSIGNALED(wstatus))40                 {41                     printf("child killed by signal,signo=[%d]\n",WTERMSIG(wstatus));42                 }43             }44             else if(wpid==0)45             {46                 printf("child is living\n");47             }48             else if(wpid=-1)49             {50                 printf("no child is living\n");51                 break;52             }53         }54     }55     return 0;56 }因为我们使用了WNOHANG让waitpid处于不阻塞状态,我们可以使用while(1)让其陷入无限循环,wpid=0时说明子进程还没结束,wpid=-1时,已经不存在子进程,break退出循环。
结果:

wait和waitpid调用一次只能清理一个子进程