OS-lab3
OS-lab3
上机
exam
我们要修改调度函数,实现多用户的(公平)进程调度,就是在Env结构体了新加一个属性:u_int env_user([0,4])(测试程序会给你赋值),最多不超过5名用户。简言之,在需要调度新的进程的时候你需要统计每个用户的总时间片选,总时间片选保存static int[] 数组中,然后你需要选出当前有进程的用户并且总时间片选最少的(相同则id最小)的用户,然后选出遍历队列选出第一个当前用户的进程。
1 |
|
extra
完成overflow的异常处理
- 请在完成异常处理函数后修改 lib/traps.c ,将你自己编写的异常处理函数加入异常向量组 中的对应位置。
- 大家可以使用 lib/genex.S 中定义的 BUILD_HANDLER 宏来构建自己的异常处理函数,构建方法可以参考已有的 handle_tlb 等处理函数。
- 异常处理(对应指令有三个add,sub,addi)
- 对于addi,addi $t, s = $t/2 + imm/2; epc += 4;
- add和sub,转换成addu和subu指令
难点是怎么从进程空间中取出指令,我们知道代码段对应页权限肯定没有PTE_D,因此在用户空间tlb访问就会异常,合理的方法是在内核态中异常处理函数,将进程中的env_va转换成物理地址,并将物理地址转换为kseg0地址
1 |
|
实验报告
一、思考题
thinking 3.1
完成进程页目录的自映射,并且将标志位设置为有效
thinking 3.2
来自elf_laod_seg函数传入,利用回调函数将程序段加载到进程制定虚拟空间中,data参数是必须的,否则我们无法得到程序段的地址
thinking 3.3
- va是否是页对齐的
- 将全部短内容加载后,实际占用的filesize是否等于memsize,如果不是则需要申请新的页空间
thinking 3.4
我们知道,进程切换是需要陷入内核态的,所以epc存储的是虚拟地址
thinking 3.5
在genex.S中
thinking 3.6
- enable_irq 设置cp0状态寄存器允许中断,即项CP0_STATUS写入(STATUS_CU0 | STATUS_IM4 | STATUS_IEc)
- timer_irq 表示响应时钟中断,执行schedule函数
thinking 3.7
先初始化时钟并且设置中断可相应,当时间片用完时表示要切换进程,发出中断陷入内核,进入handle_int函数,然后根据识别中断类型,是时钟中断然后跳转到schedule函数
二、实验难点
回调函数icode_mapper
根据elf_load_seg需要理解加载段内容到进程中可能碰到的情况,考虑是否也对齐
env_setup_vm函数实现将envs和pages拷贝到用户空间
很抽象,首先pages和evs是放在内核态代码全局变量附近,完成将这两个放到用户态指定位置,我们知道用户态是通过tlb和页表访问的,所以只需要将这两个控制块所在的页映射到用户态能访问到的UTOP到UVPT之间(在map_segment实现)但这只是实现了从内核态到内核态的平移,目的是在进程页表初始化的时候复制到进程页表,这是很巧妙的复制方法,不同虚拟空间的数据拷贝
schedule
如果要切换进程,需要判断当前队列是否为空,当前进程的状态是否仍是RUNNABLE,如果是的话需要把它放到队尾。并且切换进程是env_run所干的事
三、实验体会
经过lab0-lab3,发现linux系统实现的很巧妙,如果我们从0搭建一个操作系统真的是难上加难,所以要学习他们的思想,比如将一些很难得任务切分成小任务,然后对函数进行封装,比如加载段内容到进程中。
OS变得越来越抽象,想要学好必须要真正读懂,如果只是参考往届代码,根据提示补全代码,在上机的时候是肯定做不出来的,对于已经写好的宏和函数,要理解它们的功能和实现,在上机写的时候才能灵活应用