6.828 lab4

copy-on-write


进程创建后,子进程复制父进程的页表映射,而不是具体的物理页。那么子进程和父进程就共享了物理页中的数据。
如果此时其中一个进程要做数据修改操作,则必定会影响到另一个进程。为解决这个问题,在复制页表时,将页表中可写的页表项(有PTE_W标志)设置成只读的,并置上PTE_COW标志,表示这个页表项指定的页是copy-on-write的页。
如果其中一个进程向cow页写入数据,此时肯定会发生pagefault异常。在pagefault handler里检查这个页面是进程共享的COW页,则分配一个新的页面给该进程,并修改页表项的标志位。

内核栈

注意一个细节. 这其实是LAB3里的内容。

xv6每个进程都有自己的内核栈。当用户进程由于系统调用或中断的原因陷入内核时,会使用自己进程的内核栈。这样的话,内核随时都可以切换到另一个进程去。

jos中每个cpu有一个内核栈,而进程没有自己的内核核。这意味着同一时刻只允许有一个进程(env)处于内核态。

lab3中有解释:

Our struct Env is analogous to struct proc in xv6. Both structures hold the environment's (i.e., process's) user-mode register state in a Trapframe structure. In JOS, individual environments do not have their own kernel stacks as processes do in xv6. There can be only one JOS environment active in the kernel at a time, so JOS needs only a single kernel stack.


所以在jos中,如果某一个进程env正处于内核模式,这个进程就已经占用了内核栈。此时不允许切换到别的进程去,如何做到这一点?

jos中每个进程结构里保存了自己的Trapframe,而XV6的trapframe保存在自己进程的内核栈上。

假设,jos某个进程已经处于内核态。此时如果有个timer中断来了,由于之前已经在内核态,所以此时没有发生栈切换,要压栈的值仍然压入内核栈中。timer中断处理切换到另一个RUNABLE进程运行,这样如何返回到timer中断之前的状态(上个进程仍在内核中)呢?

trap中有这一句:

assert(!(read_eflags() & FL_IF));

保证了,如果在内核态,中断一定是关闭的。不可能由于其他原因会切换到另一个进程去。

 

进程间通信

 A 进程 用 ipc_rec() 试图接受数据,标志自己需要通信,然后换出处理器。此时进程处于ENV_NOT_RUNABLE状态。

B 进程用 ipc_send() 向某个进程发送数据。如果目标进程还没开始通信,则ipc_send()一直循环发送,阻塞在里面。直到发送成功后退出。

原文地址:https://www.cnblogs.com/sammei/p/3295606.html