Lab2实验报告
思考题
Thinking 2.1
- 编写c程序时,指针变量存储的地址是虚拟地址;
- 编写汇编程序时,
lw
、sw
指令使用的是虚拟地址。
Thinking 2.2
链表操作多项操作具有重复性,使用宏定义封装部分代码,并在链表操作时多次使用,可以大大提高可重用性和简便性。
不同链表比较:
- 单向链表:可以很好的顺序进行,但是不可以访问当前元素之前的元素;
- 双向链表:既可以正向进行,也可以逆向进行,可以直接访问当前元素之前的和之后的元素,性能较好;
- 循环链表:可以很好的顺序进行,但是不可以直接访问当前元素之前的元素,需要循环查找(单向循环列表,双向循环列表性能与普通双向链表相当);
本实验中设计的双向链表与经典双向链表不同,本实验中链表不能访问上一个元素,只能访问上一个元素的
next
指针;即本实验中链表无法访问上一个元素,只能改变上一个元素的连接关系。
Thinking 2.3
按照实验设计,选择C选项设计方案最佳:
1 | struct Page_list |
其中,pp_link
代表链表的连接单元,内含两种指针,分别是*le_next
指向链表下一个元素,**le_prev
指向链表上一个元素的*le_next
指针,可以直接改变连接顺序。pp_ref
代表链表页块计数。*lh_first
代表链表的初元素的地址。
Thinking 2.4
在一次任务中,可能会出现多个进程,同时还可能发生不同进程调用相同的虚拟内存。此时,asid
可以保证不会出现不同进程互相错误调用物理地址的问题。同时,其也可以保证系统不会进错TLB,导致TLB发生更换映射,因此也可以提高TLB效率。
Thinking 2.5
tlb_invalidate
函数如以下代码块所示:
1 | void tlb_invalidate(u_int asid, u_long va) |
tlb_out
函数如以下代码块所示:
1 | LEAF(tlb_out) |
- 在
tlb_invalidate
函数中调用了tlb_out
函数。 tlb_invalidate
函数主要实现在获得新的页表项进行更新时,对旧有表项进行删除。- 对函数
tlb_out
的解释如前文所示。
Thinking 2.6
X86 和 MIPS 在内存管理上主要有以下几点区别:
- 地址形式:X86有三种地址形式:逻辑地址、线性地址、物理地址;MIPS有两种地址形式:虚拟地址、物理地址。
- 内存管理机制:X86主要采用的是段页式管理系统,MIPS主要采用的是页式管理系统(并使用
MMU
管理内存)。 - TLB 不命中时的处理:转换失败的虚拟地址,MIPS使用
BadVAddr
寄存器存放,X86使用CR2
存放。- X86是以
CR3
作为当前进程的PGD基址,索引获得PFN后,直接输出PA。同时MMU会填充TLB以加快下次转换的速度。 - MIPS 触发TLB Refill 异常,内核的
tlb_refill_handler
会以pgd_current
为当前进程的PGD
基址,索引获得转换失败的虚拟地址对应的PTE
,并将其填入TLB,然后CPU再用刚刚转换失败的虚拟地址重新访问TLB。
- X86是以
难点分析
本次实验中,我所遇到的难点主要是以下几点:
- 宏定义的多次出现:本次实验代码中,出现大量宏定义。这样大大简便了代码逻辑性,但是也增加了阅读与编写的难度。尤其在文件众多,指导书中并未明确标注可能使用的宏定义以及其位置的情况下,初次接触内存管理并编写程序的难度极大。
- 多项函数的互相调用:本次实验中,出现大量函数。这些函数相互联系,在使用中往往需要互相调用,逻辑难度较高。同时也具有分布分散的问题,导致阅读时间较长。
- 页表及页链表的使用:本次实验中,页结构体作为重点。同时实验中大量使用一阶二阶指针,更改内容。指针指向对象复杂,逻辑难度大。页表内部属性较多,需要逐个调整。
- 二级页表的映射:实验中主要使用二级页表的结构,一级页表作为页框映射获得二级页表序号,二级页表作为页号映射获得页内容的真实物理地址。映射过程中的数据提取(该部分数据提取哪几位)及数据对应(这些数据又对应下一级数据地址的哪几位)难度较大。
实验体会
Lab2主要让我们学习有关内存管理与映射的问题,了解MIPS系统中虚拟地址与物理地址的对应关系以及在启动过程中获得与输入数据对应的真实数据。整体而言,Lab2的难度应该说是远大于前两个lab的,涉及到的知识点很多很新,同时又有大量未知的需要自己阅读的宏定义和函数(在不知道使用目的与形参函数的含义情况下上手难度极大),对于小白来说还是比较不友好,也花费了我很长一段时间来完成,不得不说,确实让我焦头烂额。因此,十分感谢那些写博客的学长,看了他们的博客后真的是茅塞顿开。操作系统的学习肯定是艰难的,还需坚定内心,勇于攀登。