实验三:虚拟内存管理
做完实验二后,大家可以了解并掌握物理内存管理中的连续空间分配算法的具体实现以及如何建立二级页表。本次实验是在实验二的基础上,借助于页表机制和实验一中涉及的中断异常处理机制,完成Page Fault异常处理和FIFO页替换算法的实现。实验原理最大的区别是在设计了如何在磁盘上缓存内存页,从而能够支持虚存管理,提供一个比实际物理内存空间“更大”的虚拟内存空间给系统使用。
实验目的:
- 了解虚拟内存的Page Fault异常处理实现
- 了解页替换算法在操作系统中的实现
实验内容:
练习0:
和lab2一样,依旧使用Ubuntu下的meld工具来进行文件拷贝,在此不再多余赘述。
练习1:给未被映射的地址映射上物理页
原理分析:
在程序的执行过程中由于某种原因导致CPU无法最终访问到相应的物理内存单元,即无法完成从虚拟地址到物理地址的映射,这时CPU会产生一次页错误异常,从而需要进行相应的页错误异常服务例程。当相关处理完成后,将返回产生异常的指令处重新执行,才能使得软件正常运行。
产生页面异常的原因主要如下:
- 目标页面不存在(页表项全为0,即该线性地址与物理地址尚未建立映射或者已经撤销);
- 相应的物理页面不在内存中(页表项非空,但Present标志位=0,比如在swap分区或磁盘文件上)
- 访问权限不符合(此时页表项P标志=1,比如企图写只读页面).
当出现上面情况之一,就会产生页面page fault(#PF)异常。产生异常的线性地址存储在CR2中,并且将是page fault的产生类型保存在 error code 中。
因此此函数是完成页错误异常处理的主要函数,他根据从CPU的控制寄存器CR2中获取的页错误异常的虚拟地址,以及根据error code的错误类型来查找次虚拟地址是否在某个VMA的地址范围内,并且是否满足正确的读写权限,如果在此范围内并且权限也正确,就认为这是一次合法访问,但没有建立虚实对应关系,所以需要分配一个空闲的内存页,并修改页表完成虚地址到物理地址的映射,刷新TLB,然后调用iret中断,返回并重新执行。如果该虚地址不在某VMA范围内,这认为是一个非法访问。(这里把vma_struct结构的变量简称为VMA变量。)
关键数据结构:
page_fault函数不知道哪些是“合法”的虚拟页,原因是ucore还缺少一定的数据结构来描述这种不在物理内存中的“合法”虚拟页。为此ucore通过建立mm_