3.LAB-5 COW

LAB-5 COW

主要是修改fork缺页中断处理程序

以前fork时,会直接复制原进程的页表内容到新页表,具体过程是

​ 对于原页表中的每一页,malloc一个新页,然后复制数据到新页,最后把这一页映射到新页表

现在进行修改:

1. fork复制页表

  1. 对于新进程,为其创建新页表
  2. 直接复用旧页表项,不复制旧物理页
  3. 如果旧页表项没有写权限,那就无需修改权限,直接复制页表项
  4. 如果有写权限,消除掉其写权限,并为其添加COW Flag

[!IMPORTANT]

如果只有新进程没有写权限,而旧进程有权限,旧进程有可能修改页内容,此时新进程将会出错,因此双方都没有写权限

2. 中断处理程序

当需要修改时,会发生缺页中断,此时再进行数据迁移

  1. 得到发生缺页的物理地址

    查看此页的引用数,如果是1,直接修改页表项,使其有写权限

  2. malloc新页

  3. 把旧页的数据复制到新页中。

  4. 修改页表,使其映射到新页

  5. 修改新页表项,使其有写权限

3. 引用计数

XV6中,页大小为4KB,页分配的最小单位也是4KB

  1. 在kinit时,初始化每一页的引用数为0
  2. kalloc时,引用数加1
  3. kfree时,引用数减1,当引用数为0时,才真的释放此页

4. 页表项Flag说明

image-20220921014023506

相关文件:kernel/riscv.h

  • PTE_V:Valid,页表项是否有效,如果未设置,则对该页的使用会引起异常(即不允许访问)。
  • PTE_R:Read,是否允许指令读取该页。
  • PTE_W:Write,是否允许写入页。
  • PTE_X:Execute,CPU是否可以将页的内容解释为指令并执行它们。
  • PTE_U:User,是否允许用户模式下的指令访问该页,如果未设置PTE_U,则只能在监督者模式下使用。

一些坑

1. 计算页号

XV6的用户内存大小是128M,一共2^15页,但是其起始地址并不是0,而是

// riscv.h
#define KERNBASE 0x80000000L

因此计算页号时,不要直接使用pa<<12获取页号,而要(pa-KERNBASE)<<12

2.uvmcopy复制页表项

复制页表项时,只有当旧表项有写权限时,才需要将其记录为cow页,

如果是只读页,无需进行这种处理,会出错。

比如0地址,存储的是二进制代码,用户态只有读权限,如果将其记录为COW页,尝试向其写入数据时,中断处理会修改这一页,导致出错

代码地址

https://github.com/INnoVationv2/xv6-labs-2023/commits/cow/

image-20240218151645416
posted @ 2024-04-21 00:11  INnoVation-V2  阅读(13)  评论(0编辑  收藏  举报