加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_阳江站长网 (https://www.0662zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux进程管理之wait系统调用

发布时间:2016-06-08 04:09:28 所属栏目:Linux 来源:站长网
导读:六: wait4 ()系统调用 在父进程中,用wait4()可以获得子进程的退出状态,并且防止在父进程退出前,子进程退出造成僵死 状态。这是我们这节分析的最后一个小节了

对僵尸进程的操作是由wait_task_zombie()完成的。代如如下:

static int wait_task_zombie(struct task_struct *p, int noreap,
         struct siginfo __user *infop,
         int __user *stat_addr, struct rusage __user *ru)
{
   unsigned long state;
   int retval;
   int status;
   //WNOWAIT被设置.不需要释放子进程的资源,只要取相关信息即可
   if (unlikely(noreap)) {
     pid_t pid = p->pid;
     uid_t uid = p->uid;
     int exit_code = p->exit_code;
     int why, status;
     //子进程不为EXIT_ZOMBIE .异常退出
     if (unlikely(p->exit_state != EXIT_ZOMBIE))
       return 0;
     //没有退出信号具没有被跟踪.退出
     if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
       return 0;
     //增加引用计数
     get_task_struct(p);
     read_unlock(&tasklist_lock);
     if ((exit_code & 0x7f) == 0) {
       why = CLD_EXITED;
       status = exit_code >> 8;
     } else {
       why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
       status = exit_code & 0x7f;
     }
//取相关信息
     return wait_noreap_copyout(p, pid, uid, why,
              status, infop, ru);
   }
   /*
   * Try to move the task's state to DEAD
   * only one thread is allowed to do this:
   */
   //将子进程状态设为EXIT_DEAD状态
   state = xchg(&p->exit_state, EXIT_DEAD);
   //如果子进程不为EXIT_ZOMBIE状态,异常退出
   if (state != EXIT_ZOMBIE) {
     BUG_ON(state != EXIT_DEAD);
     return 0;
   }
   //没有退出信号,且没有被跟踪
   if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
      return 0;
   }
   //子进程的real_parent等于当前父进程.说明子进程并没有被跟踪出去
   if (likely(p->real_parent == p->parent) && likely(p->signal)) {
     struct signal_struct *psig;
     struct signal_struct *sig;
     //更新父进程的一些统计信息
     spin_lock_irq(&p->parent->sighand->siglock);
     psig = p->parent->signal;
     sig = p->signal;
     psig->cutime =
       cputime_add(psig->cutime,
       cputime_add(p->utime,
       cputime_add(sig->utime,
            sig->cutime)));
     psig->cstime =
       cputime_add(psig->cstime,
       cputime_add(p->stime,
       cputime_add(sig->stime,
            sig->cstime)));
     psig->cmin_flt +=
       p->min_flt + sig->min_flt + sig->cmin_flt;
     psig->cmaj_flt +=
       p->maj_flt + sig->maj_flt + sig->cmaj_flt;
     psig->cnvcsw +=
       p->nvcsw + sig->nvcsw + sig->cnvcsw;
     psig->cnivcsw +=
       p->nivcsw + sig->nivcsw + sig->cnivcsw;
     psig->cinblock +=
       task_io_get_inblock(p) +
       sig->inblock + sig->cinblock;
     psig->coublock +=
       task_io_get_oublock(p) +
       sig->oublock + sig->coublock;
     spin_unlock_irq(&p->parent->sighand->siglock);
   }
   /*
   * Now we are sure this task is interesting, and no other
   * thread can reap it because we set its state to EXIT_DEAD.
   */
   //取得相关的退出信息
   read_unlock(&tasklist_lock);
   retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
   status = (p->signal->flags & SIGNAL_GROUP_EXIT)
     ? p->signal->group_exit_code : p->exit_code;
   if (!retval && stat_addr)
     retval = put_user(status, stat_addr);
   if (!retval && infop)
     retval = put_user(SIGCHLD, &infop->si_signo);
   if (!retval && infop)
     retval = put_user(0, &infop->si_errno);
   if (!retval && infop) {
     int why;
     if ((status & 0x7f) == 0) {
       why = CLD_EXITED;
       status >>= 8;
     } else {
       why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
       status &= 0x7f;
     }
     retval = put_user((short)why, &infop->si_code);
     if (!retval)
       retval = put_user(status, &infop->si_status);
   }
   if (!retval && infop)
     retval = put_user(p->pid, &infop->si_pid);
   if (!retval && infop)
     retval = put_user(p->uid, &infop->si_uid);
   if (retval) {
     // TODO: is this safe?
     p->exit_state = EXIT_ZOMBIE;
     return retval;
   }
   retval = p->pid;
   //当前进程不是生父进程.则说明进程是被跟踪出去了
   // TODO:子进程exit退出的时候,只会向其当前父进程发送信号的哦^_^
   if (p->real_parent != p->parent) {
      write_lock_irq(&tasklist_lock);
     /* Double-check with lock held. */
     if (p->real_parent != p->parent) {
       //将进程从跟踪链表中脱落,并设置父进程为生父进程
       __ptrace_unlink(p);
       // TODO: is this safe?
       //重新设置为EXIT_ZOMBI状态
       p->exit_state = EXIT_ZOMBIE;
       /*
       * If this is not a detached task, notify the parent.
       * If it's still not detached after that, don't release
       * it now.
       */
       //如果允许发送信息,则给生父进程发送相关信号
       if (p->exit_signal != -1) {
          do_notify_parent(p, p->exit_signal);
          if (p->exit_signal != -1)
            p = NULL;
}
     }
     write_unlock_irq(&tasklist_lock);
   }
   //释放子进程的剩余资源
   if (p != NULL)
     release_task(p);
   BUG_ON(!retval);
   return retval;
}

至此,我们看到了继子进程退出之后的完整处理。在此,值得注意的是。子进程在退出的时候会给父 进程发送相应的信号(例如SIG_CHILD),默认的信号处理函数也会进行相应的处理。

(编辑:应用网_阳江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!