BUAA-OS lab2实验报告,关于mos系统的内存管理机制的实现,内存初始化,二级页表,TLB重填等内容。
lab2_log
思考题
Thinking2.1
Thinking 2.1 请根据上述说明,回答问题:在编写的 C 程序中,指针变量中存储的地址是虚拟地址,还是物理地址?MIPS 汇编程序中 lw 和 sw 使用的是虚拟地址,还是物理地址?
- 都是虚拟地址,因为CPU只会发出虚拟地址,虚拟地址都需要经过映射才会得到物理地址。
Thinking2.2
Thinking 2.2 请思考下述两个问题:
• 从可重用性的角度,阐述用宏来实现链表的好处。
• 查看实验环境中的 /usr/include/sys/queue.h,了解其中单向链表与循环链表的实现,比较它们与本实验中用的双向链表,分析三者在插入与删除操作上的性能差异。
- 使用宏定义对链表的操作进行封装,提高了代码的可重用性,提高了可读性。
- 单项链表只能获取每一项的后一项,所以在某项前插入与删除的操作只能从头开始遍历链表,但可以在后一项直接插入。
- 循环链表删除插入性能与单向链表一致,但是由于有尾部指针,所以在最后一项上插入开销小。
- 双向链表在某项前后的插入操作以及对某项的删除操作都只有O(1)的开销。
Thinking2.3
Thinking 2.3 请阅读 include/queue.h 以及 include/pmap.h, 将 Page_list 的结构梳理清楚,选择正确的展开结构。
- 我选择C结构,Page_list的结构体中有一个指向表头的指针,然后每一个页的项由一个包含两个指针的pp_link与一个表示索引次数的pp_ref表示。
1 | struct Page_list{ |
Thinking2.4
Thinking 2.4 请思考下面两个问题:
• 请阅读上面有关 R3000-TLB 的描述,从虚拟内存的实现角度,阐述 ASID 的必要性。
• 请阅读《IDT R30xx Family Software Reference Manual》的 Chapter 6,结合 ASID段的位数,说明 R3000 中可容纳不同的地址空间的最大数量。
- address identifier必要性:在操作系统中,同一虚拟地址在不同的地址空间中会映射到不同的物理地址上,每个进程会有自己的虚拟地址空间,所以需要用ASID来区别改虚拟地址是在哪个进程中。
- ASID在EntryHi中占了6位,所以最大可以容纳64个地址空间。
Thinking2.5
Thinking 2.5 请回答下述三个问题:
• tlb_invalidate 和 tlb_out 的调用关系?
• 请用一句话概括 tlb_invalidate 的作用。
• 逐行解释 tlb_out 中的汇编代码。
- tlb_invalidata调用了tlb_out。
- 在页表内容改变后删除它在TLB中的旧表项。
- tlb_out代码如下:
1 | LEAF(tlb_out) |
- tlb_out由tlb_invalidate调用,主要作用就是清空TLB表项。
- 首先将cp0_entryHI的原来的值存在t0寄存器中,我们看后面可以知道主要是为了找不到的时候恢复原样用的。
- 然后就是把a0这个传入的参数写入cp0_entryHI随后用tlbp查找,得到索引值,如果大于等于0,就是找到了。
- 然后我们就可以将cp0_entryHI和cp0_entryLO都置为0,最后用tlbwi将值写到index位置的tlb里,达到清零的目的。
Thinking2.6
Thinking 2.6 任选下述二者之一回答:
• 简单了解并叙述 X86 体系结构中的内存管理机制,比较 X86 和 MIPS 在内存管理上的区别。
• 简单了解并叙述 RISC-V 中的内存管理机制,比较 RISC-V 与 MIPS 在内存管理上的区别。
- 理论课上提到了x86的内存管理机制,x86架构采用的是段页式管理机制,mips采用页式管理。
- 而且x86的页映射机制是可选的,可以通过CR0寄存器的PG位来设置。
- 除了段式的差别之外,x86的页式内存管理也与mips的有所不同,对于TLB不命中的处理机制上,mips会触发异常后TLB重填,然后第二次访问。而x86会直接索引CR3得到页目录基址,得到目标的PFN,然后再来重填TLB。
ThinkingA.1
Thinking A.1 在现代的 64 位系统中,提供了 64 位的字长,但实际上不是 64 位页式存储系统。假设在 64 位系统中采用三级页表机制,页面大小 4KB。由于 64 位系统中字长为8B,且页目录也占用一页,因此页目录中有 512 个页目录项,因此每级页表都需要 9 位。因此在 64 位系统下,总共需要 3 × 9 + 12 = 39 位就可以实现三级页表机制,并不需要 64位。
现考虑上述 39 位的三级页式存储系统,虚拟地址空间为 512 GB,若三级页表的基地址为 PTbase,请计算:
• 三级页表页目录的基地址。
• 映射到页目录自身的页目录项(自映射)。
- 三级页表页目录的基地址为: $PT_{base} + PT_{base} << 9 + PT_{base} << 18$
- 映射到页目录自身的页表项: $PT_{base} + PT_{base} << 9 + PT_{base} << 18 + PT_{base} << 27 $
难点分析
- 这次主要要操作的文件为include/queue.c与kern/pmap.c,但同时,我们离不开include/mmu.h与include/pmap.h中定义的宏。
Exercise2.1-2.5
- 这里主要需要完成内核初始化mips_init()中的两个函数
- mips_detect_memory()
page_init()
主要利用BY2PG宏,定义在mmu.h中,代表页面的大小。
然后就是实现双向链表宏,为后续做准备。
理解Page结构体的引导的链表项,指向的应该是物理空闲页的页号,通过pmap.h中的两个函数page2pa与pa2page完成于物理页面号与物理地址之间的转换。
然后就是完成管理物理内存的四个函数
- page_init, page_alloc, page_decref, page_free
Exercise2.6-2.7
- 这里主要就是虚拟内存管理的结构,我们要实现一个两级页表,一级页目录(PD),一级页表(PT),可以用PDX(va)和PTX(va)来获取一个虚拟地址的页目录号和页表号,即第31-22位与第21-12位。
- 用Pde与Pte来表示页目录项及页表项。其实就是u_long。
- MOS的满页不会置换,而是直接报错。
- pgdir_walk函数的功能是完成页目录项到页表项的映射。
- page_insert函数完成的是建立起页表与实际页控制块对应的物理页面的映射。
Exercise2.8-2.10
- TLB重填,指导书说的挺清楚的,看懂mips的汇编代码就好了~
实验体会
- 相较于lab1,lab2难度上增加很大,首先就是课下实验花费了大量的时间,但是很多地方还是不理解,我觉得最主要的还是先理解理论知识,得要先学会二级页表的寻址的规则,自映射的规则,不然会很难看懂源代码的意思。而且还有许多宏定义,一定要确保看过源代码,知道这个宏的用途。所以工作量还是很大的,但还是给自己留下了一点教训吧,os还是真的必须重视理论,这是一切的基础!而且得花时间!