[xv6]:wait-exit-kill
1. wait
xv6中并没有实现Linux中的信号(signal)机制,当一个子进程终止时,如果其父进程还未终止,那么其会将自己的state设置为ZOMBIE,
然后wakeup()正处于wait()状态的父进程,父进程遍历进程表,找到state为ZOMBIE的子进程,然后释放其资源
1 | |
2. exit
当一个进程退出时,需要让init进程收养自己的子进程
1 | |
3. kill
在xv6中, kill所做的事其实十分少
1 | |
只有短短20行,可以看出,kill并没有直接杀死进程,因为当对一个进程执行kill操作的时候,进程可能正在更新某些数据,也可能正在创建一个文件,它们还可能持有锁,因此,直接杀死进程会导致一系列问题
xv6中的做法十分温和,仅仅是将进程的killed标志位置为了1,但是对于处于SLEEPING状态的进程有着特殊处理,接下来会说
通过将进程的killed标志位置为1, 然后在一些安全的地方对killed标志位进行检查,这样可以确保进程安全的退出
来看一个例子:
trap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35void
usertrap(void)
{
...
if(r_scause() == 8){
// system call
// 第一处
if(p->killed)
exit(-1);
// sepc points to the ecall instruction,
// but we want to return to the next instruction.
p->trapframe->epc += 4;
// an interrupt will change sstatus &c registers,
// so don't enable until done with those registers.
intr_on();
syscall();
} else if((which_dev = devintr()) != 0){
// ok
} else {
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
p->killed = 1;
}
// 如果进程发现killed标志位为1,会自愿调用exit()退出
// 在这里,进程并没有持有任何的锁
// 第二处
if(p->killed)
exit(-1);
...
}在
usertrap当中,有两处这样的killed标志位检查, 当程序运行到这时,是没有锁的,并且也没有什么更新动作,即安全所以,通常,当
kill()“杀死”进程后,该进程通常不会立即死亡,而是会在下一次的某个系统调用/计时器中断/设备中断时自愿的调用exit()退出
特殊的SLEEPING
设想这样一种情况,当一个进程正在读取控制台输入,那么它会进入SLEEPING状态,而用户kill()该进程之后就没有继续理这个进程了,因此该进程就一直不会退出,因为其没有陷入trap, 所以,xv6的代码对SLEEPING状态的进程做了特殊处理,使其变为RUNNABLE,在接下来的某个时刻,中断调度线程就会调度该进程,该进程便会从sleep()中返回,下面是一个例子:
1 | |
在上面的例子中,当进程从sleep()中返回之后,便会重新进入循环,通常情况下仍然没有数据可读,进而return -1
然后回到usertrap()的syscall()处,最后检查到killed标志位为1, 自愿exit()
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!