Linux中孤儿/僵尸进程/wait/waitpid函数

孤儿进程:

概念:若子进程的父进程已经死掉,而子进程还存活着,这个进程就成了孤儿进程。

为了保证每个进程都有一个父进程,孤儿进程会被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):取得进程终止的信号编号

Linux中孤儿/僵尸进程/wait/waitpid函数_第1张图片

结果:

Linux中孤儿/僵尸进程/wait/waitpid函数_第2张图片

waitpid函数:

函数原型: pid_t waitpid(pid_t pid, int *wstatus, int options);

函数参数:

pid:

< -1   meaning  wait  for  any  child process whose process group ID is
              equal to the absolute value of pid.

       -1     meaning wait for any child process.

       0      meaning wait for any child process whose  process  group  ID  is
              equal  to that of the calling process at the time of the call to
              waitpid().

       > 0    meaning wait for the child whose process  ID  is  equal  to  the
              value of pid.

pid=-1 等待任一子进程。与wait等效。

pid>0 等待其进程id与pid相等的子进程。

options:设置为WNOHANG,函数为非阻塞,设置为0,函数阻塞。(阻塞的话父进程执行不了剩余的代码,除非子进程全部回收)

函数返回值:

>0:返回回收掉的子进程id

=-1:无子进程

=0:参数三为WNOHANG,且子进程正在运行。

使用:

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include 
  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退出循环。

结果:

Linux中孤儿/僵尸进程/wait/waitpid函数_第3张图片

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

你可能感兴趣的:(linux,运维,服务器)