xv6-4

sleep()与wakeup()以及kill() exit() wait()

这是第4篇文章了,通过阅读源码我们也应该明白:

scheduler():是由内核进程调度器转向一个调度进程

sched():是由一个进程转向内核进程调度器

好,下面我们看睡眠与唤醒

trap() -> syscall() -> sys_sleep() //主要是做获取r3中传入的参数与锁的工作

-> sleep()  // 更改进程状态并且为chan成员赋值

-> sched() // 转向内核进程调度器调度别的进程

那么是如何唤醒进程的呢?

我们从trap()中可以看到:

 switch(tf->trapno){
  case T_IRQ0 + IRQ_TIMER:
    if(cpu->id == 0){
      acquire(&tickslock);
      ticks++;
      wakeup(&ticks);
      release(&tickslock);
    }
    lapiceoi();
    break;

每次时间片中断,ticks都会加1,都会执行wakeup(),而在wakeup()(实质是wakeup1())中:

  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
    if(p->state == SLEEPING && p->chan == chan)
      p->state = RUNNABLE;

都有chan是否相等的判断。

///////////////////////////
我们在看代码的时候注意到

int
sys_sleep(void)
{
  int n;
  uint ticks0;
  
  if(argint(0, &n) < 0)
    return -1;
  acquire(&tickslock);
  ticks0 = ticks;
  //////////////////////////
  while(ticks - ticks0 < n){
    if(proc->killed){
      release(&tickslock);
      return -1;
    }
    sleep(&ticks, &tickslock);
  
  //////////////////////////
  release(&tickslock);
  return 0;
}

那么这个while是做什么的呢?
是为了kill()的顺利执行。

// Kill the process with the given pid.
// Process won't exit until it returns
// to user space (see trap in trap.c).
int
kill(int pid)
{
  struct proc *p;

  acquire(&ptable.lock);
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
    if(p->pid == pid){
      p->killed = 1;
      // Wake process from sleep if necessary.
      if(p->state == SLEEPING)
        p->state = RUNNABLE;
      release(&ptable.lock);
      return 0;
    }
  }
  release(&ptable.lock);
  return -1;
}

对于非睡眠进程,把进程结构proc的killed的成员置位即可。
然后等到时间片调度:

  // Force process exit if it has been killed and is in user space.
  // (If it is still executing in the kernel, let it keep running 
  // until it gets to the regular system call return.)
  if(proc && proc->killed && (tf->cs&3) == DPL_USER)
    exit();

  // Force process to give up CPU on clock tick.
  // If interrupts were on while locks held, would need to check nlock.
  if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
    yield();

  // Check if the process has been killed since we yielded
  if(proc && proc->killed && (tf->cs&3) == DPL_USER)
    exit();

exit()作用是设置进程以及它的子进程状态为ZOMBIE,并且让initproc接管指定进程的子进程,然后进入内核进程调度器。
而真正释放内存的是wait()。

wait():

遍历进程表,查找当前进程的子进程,然后查看子进程是否为ZOMBIE,如果是则释放资源,并且返回。

如果遍历进程表没有发现子进程,则sleep(),如此循环。

posted @ 2014-08-27 19:40  乾卦  阅读(376)  评论(0)    收藏  举报