练习0:填写已有实验
本实验依赖实验1/2/3。请把你做的实验1/2/3的代码填入本实验中代码中有“LAB1”,“LAB2”,“LAB3”的注释相应部分。
1 | vmm.c trap.c default_pmm.c pmm.c swap_fifo.c 这几个补上去就完事了 |
练习1:分配并初始化一个进程控制块
alloc_proc函数(位于kern/process/proc.c中)负责分配并返回一个新的struct proc_struct结构,用于存储新建立的内核线程的管理信息。ucore需要对这个结构进行最基本的初始化,你需要完成这个初始化过程。
【提示】在alloc_proc函数的实现中,需要初始化的proc_struct结构中的成员变量至少包括:state/pid/runs/kstack/need_resched/parent/mm/context/tf/cr3/flags/name。
1 | 很简单 按照进程控制块的内容填写就行了 |
请在实验报告中简要说明你的设计实现过程。请回答如下问题:
- 请说明proc_struct中struct context context和struct trapframe *tf成员变量含义和在本实验中的作用是啥?(提示通过看代码和编程调试可以判断出来)
1 | context 中 保存着各种寄存器的内容 这是为了保存进程上下文 为进程调度做准备 |
1 | trapframe 保存着 用于特权级转换的 栈 esp 寄存器 |
练习2:为新创建的内核线程分配资源
创建一个内核线程需要分配和设置好很多资源。kernel_thread函数通过调用do_fork函数完成具体内核线程的创建工作。do_kernel函数会调用alloc_proc函数来分配并初始化一个进程控制块,但alloc_proc只是找到了一小块内存用以记录进程的必要信息,并没有实际分配这些资源。ucore一般通过do_fork实际创建新的内核线程。do_fork的作用是,创建当前内核线程的一个副本,它们的执行上下文、代码、数据都一样,但是存储位置不同。在这个过程中,需要给新内核线程分配资源,并且复制原进程的状态。你需要完成在kern/process/proc.c中的do_fork函数中的处理过程。它的大致执行步骤包括:
- 调用alloc_proc,首先获得一块用户信息块。
- 为进程分配一个内核栈。
- 复制原进程的内存管理信息到新进程(但内核线程不必做此事)
- 复制原进程上下文到新进程
- 将新进程添加到进程列表
- 唤醒新进程
- 返回新进程号
1 | 跟着注释做就是了 |
请在实验报告中简要说明你的设计实现过程。请回答如下问题:
- 请说明ucore是否做到给每个新fork的线程一个唯一的id?请说明你的分析和理由。
1 | 可以保证 每个fork的线程 唯一ID |
练习3:阅读代码,理解 proc_run 函数和它调用的函数如何完成进程切换的
请在实验报告中简要说明你对proc_run函数的分析。并回答如下问题:
1 | 当前进程/线程 切换到 proc 这个进程/线程 |
- 在本实验的执行过程中,创建且运行了几个内核线程?
1 | 两个内核线程 一个为 idle_proc 为 第 0 个内核线程 完成内核中的初始化 然后调度执行其他进程或线程 |
- 语句local_intr_save(intr_flag);….local_intr_restore(intr_flag);在这里有何作用?请说明理由
1 | 关闭中断 避免进程切换的中途 再被中断(其他进程再进行调度) |
最后还是附上执行结果 可以去🍚了 好冷 这周怕是 2018年 广东最冷的一周了
讲讲 switch_to 切换进程
吃完饭回来了 顺便讲讲这个 switch_to 的汇编
1 | struct context { |