孤儿进程:
概念:若子进程的父进程已经死掉,而子进程还存活着,这个进程就成了孤儿进程。
为了保证每个进程都有一个父进程,孤儿进程会被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调用一次只能清理一个子进程