diff --git a/lecture_note/docs/pintos/proj3.md b/lecture_note/docs/pintos/proj3.md index 58aeaa4..99d8686 100644 --- a/lecture_note/docs/pintos/proj3.md +++ b/lecture_note/docs/pintos/proj3.md @@ -2,7 +2,7 @@ !!! warning "No plagiarism" If you are enrolled in CS130, you may not copy code from this repository. - Project 3 强调设计, 具体实现因人而异. + Project 3 强调设计, 具体实现因人而异. 如果你真的没有头绪, 可以先看看 design document 模板. !!! warning "急了急了急了" Project 3 基于 Project 2, 希望你的 Project 2 足够 robust 且有合适的非法地址检测. @@ -219,6 +219,8 @@ Pintos 的内存结构决定了我们需要管理的部分为加载可执行文 ## Task 1: Paging +### 结构 + 首先需要建立 page table 结构, 把每个 frame 需要从 user pool 取得 (`palloc_get_page (PAL_USER)`, 需要清空则改为 `palloc_get_page (PAL_USER | PAL_ZERO)` ) 的过程套壳, 方便记录信息. 在分配一个 page 之后, 需要调用 `install_page` 将 page 添加到当前进程的 page directory 中. ```c @@ -283,6 +285,39 @@ struct sup_page_table_entry { 按照 page 大小决定每个 page 需要多少 sector, 建立一个总 sector 数除以每个 page 需要的 sector 数的 bitmap, 每个 bit 代表这个 swap slot 是否被占用. +### 同步问题 + +1. 当多个进程申请 frame 时的 race condition + - `palloc_get_page` 内置了锁, 保证分配是原子的 + - 一个 frame 从 `palloc_get_page` 获取到, 另一个需要 evict frame, 两个进程的 critical section 是修改 frame table 部分, 需要加锁 + - 两个进程同时 evict frame, 需要保证不 evict 同一个 frame +2. 一个进程 page fault 时, 另一个进程正在 evict frame + - fault 申请到的新 frame 不能被 evict, 把 frame pin 住 +3. 正在被 evict 的 frame 被原来的 frame 持有者访问 + - 保证在换出等等操作之前进入如下状态: 原来持有者通过 page table 访问此 frame 时引起 page fault + - 需要使用 `pagedir_clear_page` 清除 page table 中的映射关系 +4. 正在从 disk 读取 page 时, 此 page 的 frame 不应该被其他进程 evict + - 读取完成之前不加入 frame table. +5. 在 syscall 时发生的 page fault + - 参见 Task 4 +6. 多个 page fault 的处理可以并发进行 + - 保证对同一个 frame 的操作是串行的 + - 需要 I/O 的靠 I/O 的锁互斥 + - 需要 swap 的靠 swap block 的锁互斥 + +### page fault 情况与对策 + +| 情况编号 | `not_present` | `write` | `user` | 情况 | 对策 | +| ------- | ------------- | ------- | ------ | --- | --- | +| (1) | `false` | `false` | `false` | 内核非法访问 | `kill()` | +| (2) | `false` | `false` | `true` | 用户非法访问 | `kill()` (导致 `exit(-1)` ) | +| (3) | `false` | `true` | `false` | 同理 1 (例如写不可写的内存) | 同 | +| (4) | `false` | `true` | `true` | 同理 2 | 同 | +| (5) | `true` | `false` | `false` | 在 syscall 中遇到 page fault | 尝试载入 & pin, 在 syscall 结束之前 unpin | +| (6) | `true` | `false` | `true` | 被换出/没有加载/栈增长 | 尝试载入 | +| (7) | `true` | `true` | `false` | 同 5 | 同 | +| (8) | `true` | `true` | `true` | 同 6 | 同 | + ## Task 2: Stack growth 在最开始分配一个 page 作为栈, 后续考虑栈增长的情况. 按照 80x86 PUSHA 最多在 esp 低 32 字节的位置引发 page fault, 考虑将 32 字节作为分界, 低于 32 字节时分配新的 page, 否则视为非法访问. @@ -299,4 +334,4 @@ mummap 会将文件从内存中移除, 将 dirty 的 page 写回文件. ## Task 4: Accessing user memory -需要保证在进入内核时, 用户内存是合法的, 且需要避免一些持有资源情况下遇到 page fault, 对 supplmentary page table 加入 +需要保证在进入内核时, 用户内存是合法的, 且需要避免一些持有资源情况下遇到 page fault 的情况.