BUAA OS 实验 lab2笔记

1 minute read

#

思考题

Thinking 2.1

在C程序中,指针变量存储的地址是虚拟地址。MIPS汇编程序中lw和sw使用的是虚拟地址。

Thinking 2.2

1.

用宏实现链表的好处:可重用度高,避免了重复编写,使得源程序更加简洁、易读,便于重复利用。

2.

插入:

单向列表在链表中插入只需要修改两个指针。在链表头和链表尾插入,只需要修改一个指针

循环列表需要修改无论何处插入,都需要修改两个指针。

双向链表,在链表中插入需要修改四个指针,在头尾插入需要修改2两个指针。

Thinking 2.3

C为正确的

Thinking 2.4

1.

引用自网络上对ASID的解释:ASID唯一标识每个进程,并用于为该进程提供地址空间保护,当TLB尝试解析虚拟页码时,它确保当前正在运行的进程的ASID与与虚拟页面关联的ASID匹配。 如果ASID不匹配,则将该尝试视为TLB未命中 。

对于不同的进程,其相同的虚拟地址可能对应不同的空间,因此对于不同程序,TLB需要进行区分。因此引入ASIAD,在查找TLB,需要传入虚地址和对应的ASID,这样才能正确查找到对应的物理地址。因此ASID是必不可缺的。

2.

ASID 为11-6位,共6位,故能容纳不同地址空间的最大数量为64。

Thinking 2.5

1.

tlb_invalidate调用了tlb_out

2.

根据当前进程的状态,以虚拟地址和进程的ASID值为参数调用tlb_out完成对TLB对应内容的清除

3.

LEAF(tlb_out)
.set noreorder
	mfc0    t0, CP0_ENTRYHI	//$t0 = $$EntryHi
	mtc0    a0, CP0_ENTRYHI //$EntryHi = $a0
	nop						
	/* Step 1: Use 'tlbp' to probe TLB entry */
	/* Exercise 2.8: Your code here. (1/2) */
	tlbp 					//利用EntryHi寄存器中值查找对应表项入口,并存入index寄存器
	nop
	/* Step 2: Fetch the probe result from CP0.Index */
	mfc0    t1, CP0_INDEX	//$t1 = $index
.set reorder
	bltz    t1, NO_SUCH_ENTRY// if $t1 < 0, 代表前一步操作未找到相应页,跳转NO_SUCH_ENTRY
.set noreorder
	mtc0    zero, CP0_ENTRYHI//$EntryHi = 0
	mtc0    zero, CP0_ENTRYLO0//$EntryLo = 0
	nop
	/* Step 3: Use 'tlbwi' to write CP0.EntryHi/Lo into TLB at CP0.Index  */
	/* Exercise 2.8: Your code here. (2/2) */
	tlbwi					//tlbwi,根据index寄存器中的索引将对应的EntryHi和EntryLo清零
.set reorder

NO_SUCH_ENTRY:
	mtc0    t0, CP0_ENTRYHI	//$EntryHi = $k1,将原EntryHi寄存器值写回
	j       ra				//返回
END(tlb_out)

Thinking A.1

1、三级页表页目录的基地址为: \(PD_{base} = PT_{base}+(PT_{base}>>12)*8\) 2、映射到页目录自身的页目录项 \(PDE_{self-mapping} = PD_{base} + (PT>>21)*8\)

Thinking 2.6

x86架构的内存管理分为两个部分,分段和分页。

分段提供了一种隔离每个进程或者任务代码、数据和栈模块的机制,保证多个进程或者任务能够在同一个处理器上运行而不会互相干扰。

分页机制实现了传统请求调页的虚拟内存系统,在这种系统中,程序的执行环境块按需要被映射到物理内存中。分页机制同样可以用来隔离多个任务。

对分页和分段机制进行不同的配置,可以分别支持简单的单任务系统、多任务系统或者使用共享内存的多处理器系统。

x86用到三个地址空间的概念:物理地址、线性地址和逻辑地址。而MIPS只有物理地址和虚拟地址两个概念。

难点:

1.头文件宏定义报错:使用出错,应该用指针地址

2.lab1分配段时,没有规定end的空间地址

实验难点

内核程序启动与初始化

exercise 2.1

注意页面大小为 BY2PG。根据总物理内存大小memsize计算得出。

freemem为空闲内存首地址。

注意ROUND宏函数。起作用为将地址按要求的相邻字节大小对齐。

exercise 2.2

对宏函数的理解。需要完成以宏函数为基础的双向链表。链表常用操作:

#define LIST_EMPTY(head)
#define LIST_HEAD(name, type)
#define LIST_INSERT_AFTER(listelm, elm, field)
#define LIST_INSERT_HEAD(head, elm, field)

/*
head为一个指向链表首项的指针。需要注意参数需要为一个指针对象,对于数据类型,需要传入其地址。
若宏函数未正确使用,报错会显示头文件error,而非调用错误处。
*/

注意多行宏函数,需要添加 \

#define LIST_INSERT_AFTER(listelm, elm, field)                                                     \
	do {                                                                                       \
		if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
        	(listelm)->field.le_next->field.le_prev = &(elm)->field.le_next;               \
        (listelm)->field.le_next = (elm);                               \
        (elm)->field.le_prev = &(listelm)->field.le_next;               \
	} while (0)

exercise 2.3

注意利用page2kva 获取page的地址,完成已分配内存的页面的初始化。

将地址在freemem以上的page作为空闲页,加入空闲页链表中

exercise 2.4

分配函数,在空闲链表中获取一个页面,利用page_init完成初始化,将new指针赋值为页面控制块的地址。

exercise 2.5

只需要将指定page插入空闲页链表中

exercise 2.6

Pde –(page directory 一级页表)

Pte –(page table 二级页表)

TLB 重填部分的内容需要注意练习。

注意下图中代码缩写解释

image-20230328183803796

首先需要找到指定页目录,通过PDX(va)获取索引值,访问相应页目录。

若页目录不存在,创建新的页目录,设置权限位。利用PTX(va)获取页目录项中相应页表的地址,赋值给ppte指针。

exercise 2.7

将指定page映射到一虚拟地址,并设定相应权限。

exercise 2.8 2.9 2.10

根据提示补全代码即可

实验心得与总结

相对前一个实验,此实验结构更加复杂,任务也更繁重。

很多函数的使用说明不够详细。对于一些宏定义函数,也无详细的说明,如 BY2PG等。因此也需要更完整地阅读头文件内容,才可以更顺利地进行实验。

同时,宏函数有很多对指针的利用,更有二级指针等更为复杂的利用。因此需要进一步复习c语言指针和内存管理相关的知识。

Afdafczl

Afdafczl

BUAA, School of Software, Sophomore 这是一个属于Afdaf的,基于Github Page搭建的个人博客,用于记录与查看个人学习笔记。 可点击左侧导航栏查看详情

Comments

  Write a comment ...