前言

继续lab2,大概算了下我应该至少每周一个lab,才能在两个月之内做完,感觉必须要加速了,不能再摸鱼了,毕竟不止一个ucore要学习,刚把爹,冲冲冲,注意一定要把实验指导书相关部分认真的看完!!!

正文

Part0

文件比较,我直接用clion自带的文件比较功能了,trap.c和kdebug.c两个文件改一下就可以了,复制lab1添的代码过去就行了。

Part1 实现first-fit连续物理内存分配算法

物理页架构,整个物理内存管理都是以页(Page这个结构存储了信息)作为最小单位管理的

  • ref:这个物理页被虚拟页映射的数目

  • flags:有两位,一个是PG_reserved在pmm_init` (in pmm.c)中已经被设定了,表示是否保留,PG_property需要自己设定代表了(设置的宏在memlayout.h中SetPageProperty),这个物理页是否可用,0表示被分配了或者不是头空闲页,1表示是头空闲页并且是free的

  • property:记录空闲内存快的数量,只有Page是第一个时才设定,否则如果free则设定为0

  • page_link:链接连续内存快的指针,在list.h中定义

然后是一个双向链表

  • free_list:双向链表指针
  • nr_free:当前空闲页的数目

然后正式开始我们的练习1

default_init

首先是default_init的函数,已经实现好了,init函数就是用来初始化free_area变量的

default_init_memmap

之后是default_init_memmap函数,是用来初始化某个双向链表的节点

会用到一些宏,变量

这个宏是用来设定flag的PG_property为1,即表明这个块为free的

free_area就是上面那个free_area_t struct,里面有一个双向链表的指针,一个记录空闲块数量的nr_free

原来的函数

修改后的代码

default_alloc_pages

在双向链表中寻找一个>=n的连续内存页,我们这里实现的首次匹配算法

这里在详细描述下这个空闲链表的结构,他首先是一个双向的链表,对于每个节点,nr_free是这个节点的连续空闲页的数量,然后le2page这个宏能够根据节点的指针转换为Page结构,Page结构就是上述的那个,我们这里的default_alloc_pages函数就是寻找一个需要n个连续空闲页的位置,首先在双向链表中遍历,如果有个节点的连续空闲页的数量大于等于n的话(这个信息存储在这个节点的第一个Page结构中的property中),我们拿到头空闲页page,我们需要判断是否这个节点中的空闲页数量大于需要的n,如果大于那么将起分割,分割后的起始头空闲页为p,修改位信息后,将这个p页插到page这个页后面,删除page,最后记得更新这个节点剩下的空闲页的数量并且更新page页的位信息。

default_free_pages

将想要free的n个页插回在双向链表中相应的位置,这里也是遍历双向链表的方法来寻找正确的位置

最后make qemu会显示check_alloc_page() succeeded!

Part2 实现寻找虚拟地址对应的页表项 

在有页映射机制中,ucore采用了二级页表的机制,即一个一级的页目录,一个的二级的页表,然后我们看一个线性地址的结构32位,其中高10位为页目录项的索引,中10位为页表项的索引,低十二位为物理地址的偏移,其中页目录的地址是存储在一个cr3寄存器的。

再看下ucore中的la的结构定义

get_pte主要就是由页目录,一个la(线性地址),是否创建create作为输入,首先根据输入的pgdir和la获得页表的地址,然后看PTE_P位是否设置,没有设置说明没有创建相对应的二级页表,再根据create参数来表名是否需要创建二级页表,获取物理页,设置引用,清空,设置PTE,最后利用PTX(la)获取中10位,加上我们获得页表项地址拿到物理地址,KADDR根据物理地址获取相对应的虚拟页地址

然后我们完成练习三再make qemu的会有check_pgdir() succeeded!输出

Part3 释放某虚地址所在的页并取消对应二级页表项的映射

page_remove_pte输入为页表的地址,la线性地址,需要释放的页表项,整个过程注释写很清楚,最后makee qemu看到断言都过了,然后ucore基于我们的段页式完成了lab1中的时钟中断。

总结

比预期晚了两天才完成。。。还是需要调整速度和方法,我太菜了,回头再把源码好好看看。