lab2-实验报告
THINKING
Thinking 2.1
Q::在编写的 C 程序中,指针变量中存储的地址 被视为虚拟地址,还是物理地址?MIPS 汇编程序中 lw和sw 指令使用的地址被视为虚 拟地址,还是物理地址?
**A:**均为虚拟地址
Thinking 2.2
Q2.2.1 从可重用性角度阐述用宏实现链表的好处
A:使用宏实现链表的优势在于代码的泛化能力与模块化设计。宏既实现了函数模块化和代码复用的功能,同时可以通过参数化传递数据类型或者结构体名称,使得链表不依赖与某种具体的数据类型
Q2.2.2 分析include/queue.h 中单向链表、循环链表和双向链表在插入与删除操作上的性能差异
A:
- 单项链表:只可以获取当前项的下一项
- 插入:可以在某一元素之后与链表头部直接插入(O(1)),若需要在某一项前面插入,需要遍历页表 (O(n))
- 删除:遍历删除
- 双向链表:可以获取某一项的前后两项
- 在某一元素前后插入和删除的时间复杂度都是(O(1))
- 循环链表:插入和删除同单向链表
三种链表查询效率均为(O(n))
Thinking 2.3
Q:Page_list的展开结构为
A: 我选择C选项
1 | struct Page_list{ |
Thinking 2.4
**Q:**回答以下问题
- 请阅读上面有关TLB的描述,从虚拟内存和多进程操作系统的实现角度,阐述ASID 的必要性。
- 请阅读 MIPS 4Kc 文档《MIPS32® 4K™ Processor Core Family Software User’s Manual》的 Section 3.3.1 与 Section 3.4,结合 ASID 段的位数,说明 4Kc 中可容纳 不同的地址空间的最大数量
A:ASID的必要性
- 在多进程操作系统中.不同进程拥有独立的虚拟地址空间,同一虚拟地址往往映射至不同的物理地址。ASID可以用于唯一标识物理地址空间
- 在进程切换时,使用ASID可以避免完全重写TLB与缓存,加快地址转换速度
- ASID为内存管理提供了额外保障,确保每个进程只访问自己地址空间内的内存,阻止进程越界访问。
Thinking 2.5
**Q:**回答以下问题
- tlb_invalidate和tlb_out的调用关系?
- 请用一句话概括tlb_invalidate的作用。
- 逐行解释tlb_out中的汇编代码。
A:
tlb_invalidate
调用tlb_out
,向其传入旧表项的keytlb_invalidate
实现删除特定虚拟地址在TLB中的旧表项LEAF(tlb_out) .set noreorder mfc0 t0, CP0_ENTRYHI // 将当前的CP0_ENTRYHI保存 mtc0 a0, CP0_ENTRYHI // 将需要七清楚的表项的key写入CP0_ENTRYHI nop // 冒险处理 /* Step 1: Use 'tlbp' to probe TLB entry */ /* Exercise 2.8: Your code here. (1/2) */ tlbp // 查找key对应的表项的索引 nop /* Step 2: Fetch the probe result from CP0.Index */ mfc0 t1, CP0_INDEX // key对应的表项的索引存入t1 .set reorder bltz t1, NO_SUCH_ENTRY // 如果t1是负的,及没有找到对应表项则跳转到NO_SUCH_ENTRY .set noreorder mtc0 zero, CP0_ENTRYHI // 将CP0_ENTRYHI,CP0_ENTRYLo清0 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 // 将CP0_ENTRYHI与CP0_ENTRYLo写入到index对应表项,实现表项清空 .set reorder NO_SUCH_ENTRY: mtc0 t0, CP0_ENTRYHI // 写回初始CP0_ENTRYHI(存有当前进程ASID) j ra //返回 END(tlb_out)
Thinking 2.6
**Q:**请结合 Lab2 开始的 CPU 访存流程与下图中的 Lab2 用户函数部分,尝试 将函数调用与CPU访存流程对应起来,思考函数调用与CPU访存流程的关系。
A:

Thinking 2.7
**Q:**从下述三个问题中任选其一回答:
- 简单了解并叙述X86体系结构中的内存管理机制,比较X86和MIPS 在内存管理 上的区别。
- 简单了解并叙述RISC-V 中的内存管理机制,比较RISC-V 与 MIPS 在内存管理上 的区别。
- 简单了解并叙述LoongArch 中的内存管理机制,比较 LoongArch 与 MIPS 在内存 管理上的区别。
A: RISC-V
采用基于页面的虚拟内存系统
- 分页模式与页表结构:RISC-V 支持多种分页模式(如 Sv32、Sv39、Sv48),分别对应 32 位、39 位、48 位虚拟地址空间。每个页表项(PTE)包含物理页号(PPN)、权限位(读、写、执行)、用户模式访问位(U)等。物理地址通过逐级页表遍历完成转换。
- MMU:页表基地址寄存器
satp
存储根页表物理地址和分页模式,硬件自动遍历页表,若缺页或权限错误,触发监管者模式异常,由操作系统处理。同时支持灵活的页大小,允许大页映射优化 - 物理内存保护:PMP配置寄存器定义物理内存区域的访问权限
与MIPS
区别:
- TLB管理:
RISC-V
由硬件自动遍历页表,MIPS
由软件管理,TLB触发异常时操作系统需手动遍历页表并填充 TLB - 地址空间分布:
RISC-V
无固定化用户与内核态划分,而MIPs
固定划分用户段与内核段 - 分页灵活性:
RISC-V
支持多级动态页表,而MIPS
仅支持固定层级页表
Thinking A.1
**Q:**页目录自映射
在现代的 64 位系统中,提供了 64 位的字长,但实际上不是 64 位页式存 储系统。假设在64位系统中采用三级页表机制,页面大小4KB。由于64位系统中字长为 8B,且页目录也占用一页,因此页目录中有512 个页目录项,因此每级页表都需要9位。 因此在64位系统下,总共需要3×9+12=39位就可以实现三级页表机制,并不需要64 位
现考虑上述39位的三级页式存储系统,虚拟地址空间为512GB,若三级页表的基地 址为PTbase,请计算:
- 三级页表页目录的基地址。
- 映射到页目录自身的页目录项(自映射)。
A: 页目录及地址
$$
\begin{aligned} PD_{base}&=PT_{base}+(PT_{base}>>12)<<3+((PT_{base}>>12)<<3)>>12<<3\ \end{aligned}
$$
子映射页目录项:
$$
\begin{aligned} PDE_{self-mapping}&=PD_{base}+(PD_{base}>>9)<<3\ \end{aligned}
$$
实验难点
我认为该实验的主要难点是与物理内存宏和虚拟内存管理相关的一些宏定义与函数使用
宏定义:
PDX(va)
:页目录偏移量(查找遍历页表时常用)PTX(va)
:页表偏移量(查找遍历页表时常用)PTE_ADDR(pte)
:获取页表项中的物理地址(读取 pte 时常用)PADDR(kva)
:kseg0 处虚地址 → 物理地址KADDR(pa)
:物理地址 → kseg0 处虚地址(读取 pte 后可进行转换)pa2page(u_long pa)
:物理地址 → 页控制块(读取 pte 后可进行转换)page2pa(struct Page *pp)
:页控制块 → 物理地址(填充 pte 时常用)PPN()
:物理地址→物理页框号- …
函数:
pgdir_walk
:页目录检索。在给定二级页表结构中查找对应虚拟地址的页表项page_insert
:增加地址映射。在给定二级页表结构中将虚拟地址映射到给定对应页控制块的物理页面,设定相应权限为page_alloc:
用于分配物理页面。将空闲链表头部页控制块对应的物理页面进行相应分配
实验体会
我觉得整个lab2实验内容是繁杂的,需要耗费不少精力才能准确理解物理内存、虚拟内存与TLB重填相关知识,对于其形成一个整体认知。我对于指导书精度了两遍才实现了这一目标
其次,一些链表宏、与地址转换相关的宏、函数等工具的理解使用也比较费力,需要不断去翻看指导书学习。
我在整体学习完之后,通过结构图与流程图等对于知识进行了梳理,加深了理解