BUAA操作系统lab2

Lab2实验报告
一、思考题
Thinking 2.1
在编写的 C 程序中,指针变量中存储的地址被视为虚拟地址,还是物理地址?MIPS 汇编程序中 lw和sw 指令使用的地址被视为虚拟地址,还是物理地址?
在编写的C程序中,指针变量存储的地址为虚拟地址,MIPS汇编中lw和sw使用的地址也是虚拟地址
Thinking 2.2
1)从可重用性的角度,阐述用宏来实现链表的好处。
在实验中定义的有关链表的宏是一些十分常用的对于链表的操作,而在实验中多次使用到定义的链表结构,因此相应的链表操作也是十分频繁的,通过宏来实现链表,可以让进行相关操作时不必在编写代码实现逻辑,直接使用宏即可,这省去了不必要的代码,同时提高了代码的可读性
2)查看实验环境中的/usr/include/sys/queue.h,了解其中单向链表与循环链表的实现,比较它们与本实验中使用的双向链表,分析三者在插入与删除操作上的性能差异
在这个文件中,有单向链表、双向链表和循环链表的定义,其中双向链表的定义与我们实验中使用的双向链表类似,我们可以看不同类型链表链表项的定义:
单向链表:
双向链表:
循环链表:
实现上,单向链表和循环链表类似,都有指向下一个元素的指针,其中循环链表最后一个元素相应指针指向第一个元素,同时其维护了一个指向尾项的指针,而双向链表不仅有指向下一个元素的指针,还有一个指向前一个元素的指向下一个元素的指针的指针。
操作性能:
- 单向链表:在某一项前插入,需要遍历链表,在某一项后插入,可以直接插入,删除也需要遍历链表
- 循环链表:在某一项前插入,需要遍历链表,在某一项后插入,可以直接插入,同时可以直接在尾部插入,删除需要遍历链表
- 双向链表:插入可以直接插入,但在尾部插入需要遍历链表,删除也可以直接删除
Thinking 2.3
选择Page_list正确的展开结构
阅读代码可以知道Page_list其实包含的就是一个指向Page的指针,而Page的定义如下:
即一个链表项,一个被引用次数,所以相应的Page_list的结构应该是选项C所展示:
Thinking 2.4
1)从虚拟内存和多进程操作系统的实现角度,阐述ASID的必要性
操作系统为每一个进程维护一个独立的虚拟地址空间,并维护相应的页表,所以很可能同一虚拟地址在不同进程中映射到不同的物理地址,如果没有ASID,那操作系统无法知道当前虚拟地址是在哪个地址空间,也就无法给出正确的映射,导致无法正确访问相应的物理内存
2)说明 4Kc 中可容纳不同的地址空间的最大数量
官方文档描述如下:
ASID占8位,所以4Kc中最多可容纳256个不同的地址空间
Thinking 2.5
1)tlb_invalidate和tlb_out的调用关系
tlb_invalidate调用tlb_out
2)请用一句话概括tlb_invalidate的作用
删除特定虚拟地址在TLB中的旧表项
3)逐行解释tlb_out中的汇编代码
LEAF(tlb_out)
.set noreorder
mfc0 t0, CP0_ENTRYHI
mtc0 a0, CP0_ENTRYHI
nop
/* Step 1: Use 'tlbp' to probe TLB entry */
/* Exercise 2.8: Your code here. (1/2) */
tlbp
nop
/* Step 2: Fetch the probe result from CP0.Index */
mfc0 t1, CP0_INDEX
.set reorder
bltz t1, NO_SUCH_ENTRY
.set noreorder
mtc0 zero, CP0_ENTRYHI
mtc0 zero, CP0_ENTRYLO0
mtc0 zero, CP0_ENTRYLO1
nop
/* Step 3: Use 'tlbwi' to write CP0.EntryHi/Lo into TLB at CP0.Index */
/* Exercise 2.8: Your code here. (2/2) */
tlbwi
.set reorder
tlb_out汇编代码如上,首先将ENTRYHI寄存器的值放入t0寄存器,同时将a0寄存器里面保存的参数即KEY存入ENTRYHI,再通过 tlbp 指令寻找TLB中对应的旧表项,将表项的索引放入t1寄存器,如果索引大于等于0,向ENTRYHI、ENTRYLO0、ENTRYLO1寄存器中写入0,并使用tlbwi指令将这三个寄存器的值写入相应索引的表项
Thinking 2.6
请结合 Lab2 开始的 CPU 访存流程与下图中的 Lab2 用户函数部分,尝试将函数调用与CPU访存流程对应起来,思考函数调用与CPU访存流程的关系
CPU访存流程:
函数调用:
函数调用需要将参数压入栈,这个操作需要对内存进行写,由于地址是虚拟地址,于是触发CPU访存。执行函数体时,CPU会跳转到函数入口地址,逐条开始执行指令,这时若遇到局部变量或者访存指令,又需要进行CPU的访存流程
Thinking 2.7
简单了解并叙述X86体系结构中的内存管理机制,比较X86和MIPS在内存管理上的区别
X86体系结构的内存管理是通过分段和分页协同工作实现的。
其主要思想是将内存划分为逻辑段,每个段通过段描述符定义其基址、长度和权限,当有逻辑地址时,首先将通过分段将逻辑地址转化为线性地址,针对线性地址,采用分页机制,进一步将线性地址映射到物理地址,这和MIPS体系结构相似,而分页和分段既是协同的,又是独立的,两个机制共同实现了X86体系的内存管理。
在分页机制上,两种体系的实现也不同,MIPS体系结构是通过软件来管理页表和TLB的,而X86体系结构完全是通过硬件来管理二者的。
二、难点分析
- Exercise 2.1:对相关宏定义的查找与了解
- Exercise 2.2:对双向链表的理解,尤其是对其中le_prev这个指针的理解,思考如何实现双向链表的插入、删除等操作,清楚要修改哪些值
- Exercise 2.3 - Exercise 2.5:对页结构体和页表结构体的理解,理解相应的地址变换操作,清楚该由什么地址变换到什么地址,同时熟悉链表相应宏的使用
- Exercise 2.6 - Exercise 2.7:对二级页表机制的理解,清楚相应的地址变换,熟练链表宏的使用
- Exercise 2.8 - Exercise 2.10:对TLB的组成及替换机制的理解
三、实验体会
在Lab2中,我学会了操作系统是如何去管理内存的,包括怎么实现分页机制,怎么实现TLB机制,以及如何将逻辑地址转换到物理地址。说实话,我认为本单元的难度较大,机制本身并不难以理解,甚至如果在纸面上,应该是较为简单的,但是到要真正用软件去实现这些机制的时候,我才意识到这件事到底有多么的复杂,其中有数不清的结构体的定义,有数不清的宏定义,有难以理解的链表实现,有分不清楚的指针……最关键的是,一个文件里要用到的函数、宏定义等很可能来自其他文件,一方面,可能根本不知道有哪些函数和宏可以使用,另一方面,想用某个函数和宏的时候,如果突然不太记得其功能,可这时又不知道其定义在哪个文件。总的来说,完成本单元的代码对我来说是极具挑战性的,但是最终看到测试通过的时候我也有一种成就感,为自己付出的时间感到值得。
- Title: BUAA操作系统lab2
- Author: Cdostan
- Created at : 2025-04-07 17:10:00
- Updated at : 2025-04-19 21:39:53
- Link: https://cdostan.github.io/2025/04/07/OS/Lab2实验报告/
- License: This work is licensed under CC BY-NC-SA 4.0.