Minix进程的退出

来源:互联网 发布:高冷男友知乎 编辑:程序博客网 时间:2024/05/18 02:11
参照《操作系统:设计与实现》,有些文字出自此书。
进程退出时内存管理器会调用EXIT系统调用。最终会调用mm_exit()这个函数。这个函数所作的主要工作是释放进程的内存,并将进程的子进程变成INIT的进程的子进程,成为僵死进程。主要操作的数据结构仍然为mproc[]数组表项。但当父进程在等待子进程退出时,此函数才会将表项清空。否则挂起此进程即将状态设为HANGING。等待父进程执行WAIT系统调用。WAIT系统调用最终调用do_waitpid()函数此函数和mm_exit()函数都处于/src/mm/Forkexit.c文件中。此函数在内存进程表mproc[]中查找自己的子进程,如果子进程是上面我们所说的HANGING状态,则在此函数中清空此进程的mproc[]表项。如果没有合适的子进程在此刻退出则将进程的状态WAITING状态。
源代码如下:
PUBLIC void mm_exit(rmp, exit_status)
register struct mproc *rmp; /* pointer to the process to be terminated */
int exit_status;  /* the process' exit status (for parent) */
{
/* A process is done.  Release most of the process' possessions.  If its
 * parent is waiting, release the rest, else hang.
 */
  register int proc_nr;
  int parent_waiting, right_child;
  pid_t pidarg, procgrp;
  phys_clicks base, size, s;  /* base and size used on 68000 only */
  proc_nr = (int) (rmp - mproc); /* get process slot number */
  /* Remember a session leader's process group. */
  procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
  /* If the exited process has a timer pending, kill it. */
  if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
  /* Tell the kernel and FS that the process is no longer runnable. */
  tell_fs(EXIT, proc_nr, 0, 0);  /* file system can free the proc slot */
  sys_xit(rmp->mp_parent, proc_nr, &base, &size);/*告诉系统任务此进程不可运行*/
#if (SHADOWING == 1)
  free_mem(base, size);/*释放内存*/
#endif
#if (SHADOWING == 0)/*如果为共享正文段的情况*/
  /* Release the memory occupied by the child. */
  if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
 /* No other process shares the text segment, so free it. */
 free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
  }
  /* Free the data and stack segments. */
  free_mem(rmp->mp_seg[D].mem_phys,
      rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
#endif
  /* The process slot can only be freed if the parent has done a WAIT. */
  rmp->mp_exitstatus = (char) exit_status;
  pidarg = mproc[rmp->mp_parent].mp_wpid; /* who's being waited for? */
  parent_waiting = mproc[rmp->mp_parent].mp_flags & WAITING;
  if (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp)
     right_child = TRUE;  /* child meets one of the 3 tests */
  else
     right_child = FALSE;  /* child fails all 3 tests */
  if (parent_waiting && right_child)/*如果父进程在等待状态,则清空此进程的进程表项*/
     cleanup(rmp);   /* tell parent and release child slot */
  else/*否则将此进程设为挂起状态*/
     rmp->mp_flags |= HANGING; /* parent not waiting, suspend child */
  /* If the process has children, disinherit them.  INIT is the new parent.
   * 将此进程的子进程变为INIT的子进程,如果此进程的父进程时WAITING状态而子进程是HANGING状态
   * 则清空此进程的mproc[]表项。
   */
  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
    if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
        /* 'rmp' now points to a child to be disinherited. */
        rmp->mp_parent = INIT_PROC_NR;
        parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
        if (parent_waiting && (rmp->mp_flags & HANGING)) cleanup(rmp);
    }
  }
  /* Send a hangup to the process' process group if it was a session leader. */
  if (procgrp != 0) check_sig(-procgrp, SIGHUP);
}
 
WAIT系统调用如下:
PUBLIC int do_waitpid()
{
/* A process wants to wait for a child to terminate. If one is already waiting,
 * go clean it up and let this WAIT call terminate.  Otherwise, really wait.
 * Both WAIT and WAITPID are handled by this code.
 */
  register struct mproc *rp;
  int pidarg, options, children, res2;
  /* A process calling WAIT never gets a reply in the usual way via the
   * reply() in the main loop (unless WNOHANG is set or no qualifying child
   * exists).  If a child has already exited, the routine cleanup() sends
   * the reply to awaken the caller.
   */
  /* Set internal variables, depending on whether this is WAIT or WAITPID. */
  pidarg  = (mm_call == WAIT ? -1 : pid); /* first param of waitpid */
  options = (mm_call == WAIT ?  0 : sig_nr); /* third param of waitpid */
  if (pidarg == 0) pidarg = -mp->mp_procgrp; /* pidarg < 0 ==> proc grp */
  /* Is there a child waiting to be collected? At this point, pidarg != 0:
   * pidarg  >  0 means pidarg is pid of a specific process to wait for
   * pidarg == -1 means wait for any child
   * pidarg  < -1 means wait for any child whose process group = -pidarg
   */
  children = 0;
  for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
 if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
  /* The value of pidarg determines which children qualify. */
  if (pidarg  > 0 && pidarg != rp->mp_pid) continue;
  if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
  children++;  /* this child is acceptable */
  if (rp->mp_flags & HANGING) {/*查看mproc[]表项,看是否有子进程处于HANGING状态*/
   /* This child meets the pid test and has exited. */
   cleanup(rp); /* this child has already exited */
   dont_reply = TRUE;
   return(OK);
  }
  if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
   /* This child meets the pid test and is being traced.*/
   res2 =  0177 | (rp->mp_sigstatus << 8);
   reply(who, rp->mp_pid, res2, NIL_PTR);
   dont_reply = TRUE;
   rp->mp_sigstatus = 0;
   return(OK);
  }
 }
  }
  /* No qualifying child has exited.  Wait for one, unless none exists. */
  if (children > 0) {/*如果仍有子进程存在,则将进程设为WAITING状态*/
 /* At least 1 child meets the pid test exists, but has not exited. */
 if (options & WNOHANG) return(0);    /* parent does not want to wait */
 mp->mp_flags |= WAITING;      /* parent wants to wait */
 mp->mp_wpid = (pid_t) pidarg;      /* save pid for later */
 dont_reply = TRUE;       /* do not reply now though */
 return(OK);        /* yes - wait for one to exit */
  } else {
 /* No child even meets the pid test.  Return error immediately. */
 return(ECHILD);        /* no - parent has no children */
  }
原创粉丝点击