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(),如此循环。

浙公网安备 33010602011771号