xv6_lab5 COW
Problem xv6 中的 fork() 系统调用会将父进程的所有用户空间内存复制到子进程中,如果父进程很大,复制过程可能会花费很长时间。 更糟糕的是,这项工作通常是多余的:子进程 fork() 后面通常跟着 exec(),会丢弃复制的内存,通常不会使用其中的大部分。 另一方面,如果父进程和子进程都使用复制的页面,并且其中一个或两个都对其进行了写入,则复制确实是必要的。 Analysis 实现 copy-on-write (COW) fork() 的目标是推迟 allocating 和 copying 物理内存页面,直到实际需要复制为止(如果有的话)。 COW fork() 只会为子进程创建一个页表,其中用户内存的 PTE 指向父进程的物理页面。COW fork() 将父进程和子进程中的所有用户 PTE 标记为只读。当任何一个进程尝试写入其中一个 COW 页面时,CPU 都会强制触发 page fault。内核 page fault handler 会检测到这种情况,为发生错误的进程分配 a page of physical memory,将 original page 复制到 new page 中,并修改发生错误的进程中相关的 PTE 指向 new page,此时 PTE 标记为可写。当 page fault handler 返回时,用户进程将能够写入 page。 这边父进程和子进程都需要将 pte 标记为只读,这样在写任意一个进程发生 page fault 时,内核都会分配一个新页,并复制原始页的内容到新页,做到进程隔离。 如果只标记子进程的 pte 为只读,那么如果父进程先写入,则不会触发 page fault,从而不会分配新页,而在原来的页上修改。而此时子进程的 virtual address 还指向原来的页,内容也被修改了。...