练习1:给未被映射的地址映射上物理页(需要编程)
本实验要求完成do_pgfault
函数,作用给未被映射的地址映射上物理页。
具体而言,当启动分页机制以后,如果一条指令或数据的虚拟地址所对应的物理页框不在内存中或者访问的类型有错误(比如写一个只读页或用户态程序访问内核态的数据等),就会发生
页错误异常。产生页面异常的原因主要有:
1.目标页面不存在(页表项全为0,即该线性地址与物理地址尚未建立映射或者已经撤销);
2.相应的物理页面不在内存中(页表项非空,但Present标志位=0,比如在swap分区或磁盘文件上);
3.访问权限不符合(此时页表项P标志=1,比如企图写只读页面)。
当出现上面情况之一,那么就会产生页面page fault(#PF)
异常。产生异常的线性地址存储在
CR2中,并且将page fault
的产生类型保存在error code
中那么我们的这个do_pgfault
函数的思路就明显了。do_pgfault()
函数从CR2寄存器中获取页错误异常的虚拟地址,根据error code
来查找这个虚拟地址是否在某一个VMA的地址范围内,那么就给它分配一个物理页。
在kern/init/init.c
中新增了几个部件的初始化:
vmm_init(); // init virtual memory management
ide_init(); // init ide devices
swap_init(); // init swap
第一个函数vmm_init是检查我们的练习1是否正确实现了。
ide_init和swap_init是为练习2准备的。由于页面置换算法的实现存在对硬盘数据块的读写,所以ide_init
就是完成对用于页换入换出的硬盘(简称swap硬盘)的初始化工作。完成ide_init
函数后,ucore就可以对这个swap硬盘进行读写操作了。swap_init
函数首先建立swap_manager
,swap_manager
是完成页面替换过程的主要功能模块,其中包含了页面置换算法的实现。
page_fault
函数不知道哪些是“合法”的虚拟页,原因是ucore还缺少一定的数据结构来描述这种不在物理内存中的“合法”虚拟页。**为此ucore通过建立mm_struct
和vma_struct
数据结构,描述了ucore模拟应用程序运行所需的合法内存空间。**当访问内存产生page fault
异常时,可获得访问的内存的方式(读或写)以及具体的虚拟内存地址,这样ucore就可以查询此地址,看是否属于vma_struct
数据结构中描述的合法地址范围中,如果在,则可根据具体情况进行请求调页/页换入换出处理(这就是练习2涉及的部分);如果不在,则报错。
这里的vma是描述应用程序对虚拟内存“需求”的变量,如下:
// the virtual continuous memory area(vma)
// 虚拟连续内存区域,描述应用程序对虚拟内存“需求”的数据结构
struct vma_struct {
struct mm_struct *vm_mm; // the set of vma using the same PDT
// vm_start和vm_end描述了一个连续地址的虚拟内存空间的起始位置和结束位置,vma之间的地址空间无交集
uintptr_t vm_start; // start addr of vma
uintptr_t vm_end; // end addr of vma
uint32_t vm_flags; // flags of vma 虚拟内存空间的属性,包括:只读、可读写、可执行
list_entry_t list_link; // linear list link which sorted by start addr of vma 根据起始地址排序的链表结点
};
mm_struct
的结构如下:
// the control struct for a set of vma using the same PDT
// 对所有“属于同一页目录表”的虚拟内存空间进行控制的结构
struct mm_struct {
list_entry_t mmap_list; // linear list link which sorted by start addr of vma 链接了所有属于同一页目录表的虚拟内存空间
struct vma_struct *mmap_cache; // current accessed vma, used for speed purpose 当前使用的虚拟内存空间,由于程序局部性原理,能够加速访问
pde_t *pgdir; // the PDT of these vma 维护的页表
int map_count; // the count of these vma
void *sm_priv; // the private data for swap manager
};
最终得到do_pgfault
函数如下:
/* do_pgfault - interrupt handler to process the page fault execption 处理缺页中断异常的中断处理器
* @mm : the control struct for a set of vma using the same PDT 对存在相同页目录表的vma的控制结构
* @error_code : the error code recorded in trapframe->tf_err which is set by x86 hardware 记录在trapframe->tf_err中的错误码,由硬件设置
* @addr : the addr which causes a memory access exception, (the contents of the CR2 register) 引起内存访问异常的地址(CR2寄存器的内容)
*
* CALL GRAPH: trap--> trap_dispatch-->pgfault_handler-->do_pgfault
* The processor provides ucore's do_pgfault function with two items of information to aid in diagnosing
* the exception and recovering from it. 处理器提供了两个信息给do_fault函数处理异常
* (1) The contents of the CR2 register. The processor loads the CR2 register with the
* 32-bit linear address that generated the exception. The do_pgfault fun can
* use this address to locate the corresponding page directory and page-table
* entries.
* CR2寄存器的内容。处理器将引起中断的32位线性地址加载到CR2寄存器中,函数可以用该地址定位相应的页目录、页表项
* (2) An error code on the kernel stack. The error code for a page fault has a format different from
* that for other exceptions. The error code tells the exception handler three things:
* 存在内核栈中的错误码。缺页异常的错误码和其他异常的错误码各式不同,它告知处理器三件事情:
* -- The P flag (bit 0) indicates whether the exception was due to a not-present page (0)
* or to either an access rights violation or the use of a reserved bit (1).
* P位,指出页不在内存中还是违反了访问权限/保留位为1
* -- The W/R flag (bit 1) indicates whether the memory access that caused the exception
* was a read (0) or write (1).
* W/R位,指出引起异常的是读还是写
* -- The U/S flag (bit 2) indicates whether the processor was executing at user mode (1)
* or supervisor mode (0) at the time of the exception.
* U/S位,指出出现异常时机器处于内核态还是用户态
*/
int
do_pgfault(struct mm_struct *mm, uint32_t error_code, uintptr_t addr) {
int ret = -E_INVAL;
//try to find a vma which include addr
struct vma_struct *vma = find_vma(mm, addr); // find a vma (vma->vm_start <= addr <= vma_vm_end)
pgfault_num++;
//If the addr is in the range of a mm's vma?