【OS】BUAA-OS-Lab2-实验报告

OS Lab2实验报告

思考题

Thinking 2.1

请根据上述说明,回答问题:在编写的 C 程序中,指针变量中存储的地址 被视为虚拟地址,还是物理地址?MIPS 汇编程序中 lw和sw 指令使用的地址被视为虚 拟地址,还是物理地址?
答:均为虚拟地址

Thinking2.2

请思考下述两个问题:

  • 从可重用性的角度,阐述用宏来实现链表的好处。
  • 查看实验环境中的/usr/include/sys/queue.h,了解其中单向链表与循环链表的实 现,比较它们与本实验中使用的双向链表,分析三者在插入与删除操作上的性能差异

答:用宏来实现链表可以方便进行代码复用,使代码更加清晰可读。

  • 单项链表在删除某一节点时需要遍历链表以找到该节点前的节点,同时插入时若要在某一节点前插入也需要遍历,这就导致其性能较差;
  • 循环链表相比与单项链表多了一个指向尾部的指针,性能差异也只有在尾部节点后插入时才会比单向链表好,其他情况下性能相同。
  • 双向链表对于删除和插入都有更好的表现,但是相比于循环链表,在链表尾部插入时性能不如循环链表,需要遍历找到尾部节点。

Thinking2.3

请阅读include/queue.h以及include/pmap.h,将Page_list的结构梳 理清楚,选择正确的展开结构。

答:

1
2
3
4
5
6
7
8
9
C:struct Page_list {
struct {
struct {
struct Page *le_next;
struct Page **le_prec;
} pp_link;
u_short pp_ref;
}* lh_first;
}

Thinking 2.4

请思考下面两个问题:

  • 请阅读上面有关TLB的描述,从虚拟内存和多进程操作系统的实现角度,阐述ASID 的必要性。
  • 请阅读 MIPS 4Kc 文档《MIPS32® 4K™ Processor Core Family Software User’s Manual》的 Section 3.3.1 与 Section 3.4,结合 ASID 段的位数,说明 4Kc 中可容纳不同的地址空间的最大数量。

答:

  • 由于不同的进程中的虚拟地址是独立的,因此不同进程中的同一虚拟地址可能对应着不同的物理地址,需要通过ASID来标识是哪个进程的虚拟地址,为TLB提供翻译的依据,TLB 条目包含 ASID 标记,使得操作系统可以同时维护多个进程的地址映射而无需频繁刷新 TLB。当发生进程切换时,操作系统只需更新当前进程的 ASID,而不必使整个 TLB 失效
  • 4Kc中ASID有8位,因此可以容纳256个不同的地址空间。

    In this figure the virtual address is extended with an 8-bit address-space identifier (ASID), which reduces the frequency of TLB flushing during a context switch. This 8-bit ASID contains the number assigned to that process and is stored in the CP0 EntryHi register.

Thinking2.5

请回答下述三个问题:

  • tlb_invalidate和tlb_out的调用关系?
  • 请用一句话概括tlb_invalidate的作用。
  • 逐行解释tlb_out中的汇编代码。

答:

  • tlb_invalidate调用tlb_out
  • 在页表更新后对TLB更新
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    LEAF(tlb_out)
    nop
    mfc0 k1,CP0_ENTRYHI //从EntryHi中取出值并存入k1寄存器
    mtc0 a0,CP0_ENTRYHI //将a0存入EntryHi寄存器
    nop
    tlbp //在TLB中查找EntryHi中的值对应的表项并存入Index寄存器
    nop
    nop
    nop
    nop
    mfc0 k0,CP0_INDEX //从Index中取出值并存入k0寄存器
    bltz k0,NOFOUND //如果k0小于零,跳转到NOFOUND处,此时在TLB中没有找到对应的表项
    nop
    mtc0 zero,CP0_ENTRYHI //EntryHi赋值为0
    mtc0 zero,CP0_ENTRYLO0 //EntryLo0赋值为0
    nop
    tlbwi //将EntryHi和EntryLo0寄存器中的值写入Index指定的TLB表项
    NOFOUND:

    mtc0 k1,CP0_ENTRYHI //复原调用前的状态
    j ra //返回
    nop
    END(tlb_out)

Thinking 2.6

请结合 Lab2 开始的 CPU 访存流程与下图中的 Lab2 用户函数部分,尝试将函数调用与CPU访存流程对应起来,思考函数调用与CPU访存流程的关系。

答:
调用函数时执行jal func跳转到 func,同时将返回地址(PC+8)写入 $ra,将可能需要用到的寄存器的原有值保存到栈,函数内部也可能进行访存,执行结束后用栈中的值恢复寄存器,然后通过jr $ra回到原地址。

Thinking 2.7

从下述三个问题中任选其一回答:
• 简单了解并叙述X86体系结构中的内存管理机制,比较X86和MIPS 在内存管理 上的区别。
• 简单了解并叙述RISC-V 中的内存管理机制,比较RISC-V 与 MIPS 在内存管理上 的区别。
• 简单了解并叙述LoongArch 中的内存管理机制,比较 LoongArch 与 MIPS 在内存 管理上的区别。

答:

  • x86采用段页式的内存管理机制,MIPS采用纯页式的机制,设计更简单。
  • x86的TLB缓存最近使用的页表条目,硬件自动填充,MIPS的TLB由软件显式管理
  • x86的页表管理是通过硬件自动遍历多级页表,MIPS由软件进行页表管理

难点分析

从知识角度来说,此次实验的难点在于页式存储结构的建立和多级页表这一页表管理机制,以及虚拟地址和物理地址的转换。要注意虚拟地址所在的位置是哪一部分(kuseg、kuseg0等等)从而确定物理地址的转换方法;一级页表中存在自映射机制,一级页表本身也是其中一张二级页表,这一点对于理解好页表的起点还是挺重要的。
从代码角度来说,难点在于实验代码中复杂的宏,要去读宏定义,清楚有哪些宏,宏的定义是什么,有什么作用,对宏有了较为清晰的掌握才能更好地阅读代码。

实验体会

还是要把实验代码完整地去读一下,不能嫌麻烦,这一次就是一开始嫌弃宏太多导致读完代码也感觉似懂非懂,多读了几遍才明白怎么回事,如果先对各种宏了解好或许能提高第一次读代码的理解效率。还有就是实验指导书还是得多读几遍,不仅是因为内容晦涩,更是因为指导书全局性比较强,必须通读后再回过头来细读才能有个更好的理解和体会。

原创性说明

本报告为本人原创


【OS】BUAA-OS-Lab2-实验报告
http://example.com/2025/04/11/【OS】BUAA-OS-Lab2-实验报告/
作者
mRNA
发布于
2025年4月11日
许可协议