BUAA-OS-LAB2
BUAA OS LAB2 实验报告
Thinking
Thinking 2.1
Q:
请根据上述说明,回答问题:在编写的 C 程序中,指针变量中存储的地址 被视为虚拟地址,还是物理地址?MIPS 汇编程序中 lw和sw 指令使用的地址被视为虚 拟地址,还是物理地址?
A:
实际程序中,访存、跳转等指令以及用于取指的PC寄存器中的访存目标地址都是虚拟地址。我们编写的C程序中中指针的值也是虚拟地址。
Thinking 2.2
Q:
•从可重用性的角度,阐述用宏来实现链表的好处。
•查看实验环境中的/usr/include/sys/queue.h,了解其中单向链表与循环链表的实 现,比较它们与本实验中使用的双向链表,分析三者在插入与删除操作上的性能差 异。
A:
宏的的特性就是可重复使用。当这段代码的具体实现需要更改时,只需要改宏这一处就行。宏相比函数由于是字符串的替换,因此不必进行地址的跳转和栈的保存。
在实验环境中,只看到了单向链表、双向链表、单向队列、双向队列、循环队列,感觉循环队列在插入和删除操作方面和循环链表没太大差异,据此进一步分析。
插入操作:单向链表插入操作十分简单,两行代码,双向链表插入操作一般运行四行代码,需要额外判断是否next指向了NULL,循环链表与双向链表运行代码量基本相等,需额外判断是否next指向了头指针。特别的是,插入到头结点对三种链表而言性能相似,单向链表与双向链表插入到尾结点均要遍历完整个链表。
删除操作:单向链表的删除操作复杂度为O(n),因为需要靠循环才能找到上一个链表节点的位置,双向链表及循环链表的删除操作与插入性能相近,也还是需要额外判断NULL或HEAD。删除头结点对三种链表而言性能相似,而单向链表与双向链表删除尾结点还是要遍历。
Thinking 2.3
Q:
请阅读include/queue.h以及include/pmap.h,将Page_list的结构梳 理清楚,选择正确的展开结构。
1
2
3
4
5
6
7
8
9
10 A:
structPage_list{
struct {
struct{
structPage *le_next;
structPage *le_prev;
}pp_link;
u_shortpp_ref;
}*lh_first;
}
1
2
3
4
5
6
7
8
9
10 B:
structPage_list{
struct {
struct{
structPage *le_next;
structPage **le_prev;
}pp_link;
u_shortpp_ref;
} lh_first;
}
1
2
3
4
5
6
7
8
9
10 C:
structPage_list{
struct {
struct{
structPage *le_next;
structPage **le_prev;
}pp_link;
u_shortpp_ref;
}*lh_first;
}
A:
答案选C。Page_list中含有的是Page结构体指针头。每一个Page内存控制块都有一个pp_ref
用于表示其引用次数(为0时便可remove),还有一个结构体用于存放实现双向链表的指针。
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可以判断是在哪个地址空间。例如有多个进程都用到了这个虚拟地址,但若该虚拟地址对应的数据不是共享的,则基本可以表明指向的是不同物理地址,这也是一种对地址空间的保护。
可容纳不同地址空间的最大数量:MIPS 4Kc处理器通过8位ASID字段,最多可支持256个不同的地址空间。
Thinking 2.5
Q:
请回答下述三个问题:
•tlb_invalidate和tlb_out的调用关系?
•请用一句话概括tlb_invalidate的作用。
•逐行解释tlb_out中的汇编代码。
A:
tlb_invalidate调用tlb_out
调用tlb_invalidate可以将该地址空间的虚拟地址对应的表项清除出去,一般用于这个虚拟空间引用次数为0时释放tlb空间
1 | LEAF(tlb_out) |
Thinking 2.6
Q:
请结合 Lab2 开始的 CPU 访存流程与下图中的 Lab2 用户函数部分,尝试 将函数调用与CPU访存流程对应起来,思考函数调用与CPU访存流程的关系。

A:
函数调用与CPU访存的关系总结
- 初始化阶段:
通过env_setup_vm
、page_alloc
等函数构建进程的页表框架,为后续访存提供基础设施。 - 主动映射阶段:
load_icode
和map_segment
预先建立关键映射(如代码段),减少运行时TLB未命中次数。 - 动态映射阶段:
运行时未映射的虚拟地址访问触发do_tlb_refill
,依赖passive_alloc
和page_insert
动态分配物理页并更新页表,体现“按需分配”特性。 - 一致性维护:
映射变更后(如page_insert
),通过tlb_invalidate
确保TLB与页表一致,避免脏数据访问。
Thinking 2.7
Q:
从下述三个问题中任选其一回答:
• 简单了解并叙述X86体系结构中的内存管理机制,比较X86和MIPS 在内存管理 上的区别。
• 简单了解并叙述RISC-V 中的内存管理机制,比较RISC-V 与 MIPS 在内存管理上 的区别。
• 简单了解并叙述LoongArch 中的内存管理机制,比较 LoongArch 与 MIPS 在内存 管理上的区别。
A:
内存管理机制对比表(X86、MIPS、RISC-V、LoongArch)
特性 | X86 | MIPS | RISC-V | LoongArch |
---|---|---|---|---|
地址转换机制 | 分段 + 分页混合机制 | 纯分页机制 | 纯分页机制(支持 Sv32/Sv39/Sv48) | 纯分页机制(多级页表) |
分段机制 | 支持(强制逻辑地址分段) | 无 | 无 | 无 |
分页机制 | 多级页表(32位二级,64位四级/五级) | 固定页表结构(TLB映射) | 灵活分页模式(Sv32/Sv39等) | 多级页表(类似X86,支持大页) |
TLB 管理 | 硬件自动处理 TLB 未命中 | 软件处理 TLB 未命中(异常机制) | 可选硬件加速或软件处理 | 硬件辅助 TLB 填充(部分自动化) |
权限控制 | 分段和分页双重保护(Ring 0~3) | 分页权限位 + 固定内核/用户区域 | 分页权限位(U/S/M模式) | 分页权限位 + 特权级隔离 |
物理地址扩展 | PAE 或 64 位扩展(48~52位) | TLB 条目扩展(支持40~64位) | 分页模式扩展(如Sv39支持56位) | 多级页表扩展(支持大物理地址) |
地址空间划分 | 分段划分逻辑空间 | 固定内核/用户区域(如 kseg0 ) |
灵活划分(用户/内核地址空间) | 固定内核映射区域 + 用户空间 |
兼容性设计 | 保留分段以兼容历史架构 | 无历史包袱,设计简单 | 模块化设计,无历史兼容负担 | 自主研发,兼容性设计较少 |
典型应用场景 | 通用计算(PC/服务器) | 嵌入式/早期游戏主机/路由器 | 嵌入式/IoT/新兴处理器 | 国产高性能计算/服务器 |
lab2难点
T1
除以页大小得到页数。
1 | void mips_detect_memory(u_int _memsize) { |
T2
注意顺序,先将新添加的表项链接到前后,再修改原先的链接顺序。
注意prev指针指向的是前一项的next指针,是一个二重指针。
1 |
|
T3
page_free_list
是一个page_list
类型,该类型在宏定义里用PAGE_HEAD()
定义为了一个链表头部。
PADDR()
将虚拟地址转换为物理地址,
1 | void page_init(void) { |
T4
memset()需要的是虚拟地址,需要page2kva()
将页转换为虚拟地址。
1 | int page_alloc(struct Page **new) { |
T5
1 | void page_free(struct Page *pp) { |
T6
如图,顺序已经十分清楚了。

1 | static int pgdir_walk(Pde *pgdir, u_long va, int create, Pte **ppte) { |
T7
1 | int page_insert(Pde *pgdir, u_int asid, struct Page *pp, u_long va, u_int perm) { |
T8
1 | LEAF(tlb_out) |
T9
1 | void _do_tlb_refill(u_long *pentrylo, u_int va, u_int asid) { |
T10
1 | NESTED(do_tlb_refill, 24, zero) |
实验体会总结
这次实验最麻烦的一点是信息量巨大,需要看懂许多的结构体和定义函数的使用方法,而且还有物理地址、虚拟地址、二级页表页号等的转换,TLB也是涉及大量地址转换。
体会:
- 需要多看课程组的Hint,好几个不知道值的参数都是宏定义
- 一般情况下用的都是虚拟地址,只有填入内容才会使用物理地址
- 对于c语言结构体和指针的使用需要熟悉