研究xv6-riscv新知汇总

本文最后更新于:2023年5月6日 晚上

研究xv6-riscv新知汇总

按理来说,分页机制那一篇文章应该归到这里的第一个新知的。但是事实上,我到在现在才想起来汇总,惭愧啊,实在是怠惰了😅

Copy On Write

写时复制,亦即COW(Copy On Write),是一种在操作系统或者数据库等系统中常用到的策略。它的主要思想是,在多个进程或者线程请求同一段数据空间时,他们会共同指向这一段空间,也就是说他们共享这些数据。只有在其中一个进程/线程请求写入数据时,才将这段数据空间复制一份。这样在如今多数以读取数据为主的数据操作中,这种策略可以大量节省空间资源,同时提高操作效率。

xv6-riscv在fork时会产生父子两个进程,采用的资源共享策略就是COW,我们来看看它是如何实现的:

首先进程在fork之后,会产生一个子进程,这个进程的内存空间和父进程的一摸一样。具体来说就是页表和物理页都完全相同。然后因为此时还没有任何的写入操作,物理页中的flags中的PTE_W=0也就是只读的。

当父子进程中的一个开始写一个页的时候,操作系统就触发一个缺页中断(page fault),自然而然调用中断处理函数,这个处理函数(handler)做了这样几件事:

  1. 使用空闲物理地址分配一个新的物理页,并复制缺页中断的那页内容到该新页

  2. 将缺页的PTE映射到新创建的物理页上(具体用mappages函数实现)

  3. 使这个新的页的权限变为可写(PT_W=1)

  4. 还原到原来中断发生的指令上

然后指令继续运行,并在这一次写入成功(当然写入的是新分配的物理地址)

需要注意的是,xv6-riscv在实现COW时创建了一种数据结构,这种数据结构用来存储一个页表被引用的次数:

  • 1代表没有fork,不需要copy

  • 2就代表着fork发生了,需要注意写请求的出现