MIT 6.S081 第五章笔记 | 页面故障
当视图访问 \(PTE_V\) 为 \(0\) 的页表, 或用户尝试访问 \(PTE_U\) 为 \(0\) / 内核尝试访问 $PTE_U 为 \(1\) 的页表, 或者是其他违反了 \(PTE_R\) 或 \(PTE_W\) 等 \(flag\) 的页表时就会出现 \(Page Faults\)。
一共有三种 \(Page Faults\): 1. \(load \space page \space faults\):
当load
指令无法解析虚拟地址时发生。 2. \(store \space page \space faults\):
当store
指令无法解析虚拟地址时发生。 3. \(instructions \space page \space faults\):
当无法解析一条指令所在的虚拟地址时发生。
\(page \space faults\)
种类的代码存放在scause
寄存器中,无法翻译的地址存放在stval
寄存器中。
在xv6中对于 \(exception\) 一律都会将这个进程kill掉,但是实际上可以结合\(page \space faults\) 实现一些功能。
- 可以实现 \(\textbf{copy-on-write} \space
\textbf{fork}\)。在
fork()
时,一般都是将父进程的所有\(user \space memory\) 复制到子进程中,但是fork
之后一般会直接进行exec
,这就会导致复制过来的 \(user \space memory\) 又被放弃掉。因此改进的思路是:子进程和父进程共享一个物理内存,但是mapping时将PTE_W置零,只有当子进程或者父进程的其中一个进程需要向这个地址写入时产生page fault,此时才会进行copy。 - 可以实现 \(\textbf{lazy} \space
\testbf{allocation}\)。旧的
sbrk()
申请分配内存,但是申请的这些内存进程很可能不会全部用到,因此改进方案为:当进程调用sbrk()
时,将修改p->sz
,但是并不实际分配内存,并且将PTE_V置0。当在试图访问这些新的地址时发生page fault再进行物理内存的分配。 - \(\textbf{paging} \space \textbf{from} \space \textbf{disk}\):当内存没有足够的物理空间时,可以先将数据存储在其他的存储介质(比如硬盘)上,将该地址的PTE设置为\(invalid\),使其成为一个驱逐页(\(evicted page\))。当需要读或者写这个PTE时,产生Page fault,然后在内存上分配一个物理地址,将这个硬盘上的evicted page的内容写入到该内存上,设置PTE为valid并且引用到这个内存物理地址。
这两节没有什么新东西,主要就是结合前面三章的内容灵活应用,讲解一些操作系统的优化。更多在于理解为什么现代操作系统要这么设计(一个虚拟内存玩出花来了属于是)。
MIT 6.S081 第五章笔记 | 页面故障
https://acmicpc.top/2024/02/29/MIT-6.S081-lab05 Notes/