操作系统ucore lab3实验报告
2017-04-25 00:47
387 查看
练习0
填写已有实验本实验依赖实验1和实验2.请把要做的实验1的代码填入本实验中代码有lab1、lab2的注释相应部分
首先利用meld工具比较两个文件的差异
发现缺失的是
kdebug.c、trap.c、default_pmm.c、pmm.c四个文件的相关代码,补全后进行下一练习
练习1
给未被映射的地址映射上物理页(需要编程)完成
do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页。设置访问权限的时候需要参考页面所在VMA的权限,同时需要注意映射物理页时需要操作内存控制结构所制定的页表,而不是内核的页表。
原理分析
在程序的执行过程中由于某种原因(页框不存在/写只读页等)而是CPU无法最终访问到相应的物理内存单元,即无法完成从虚拟地址到物理地址的映射是,CPU会产生一次页错误异常,从而需要进行相应的页错误异常服务例程。当相关处理完成后,将返回产生异常的指令处重新执行,使得软件正常运行。[b]产生页面异常的只要原因如下:[/b]
目标页面不存在(页表项全为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变量。
vma_struct
struct vma_struct { // the set of vma using the same PDT struct mm_struct *vm_mm; uintptr_t vm_start; // start addr of vma uintptr_t vm_end; // end addr of vma uint32_t vm_flags; // flags of vma //linear list link which sorted by start addr of vma list_entry_t list_link; };
vm_start和
vm_end描述了一个连续地址的虚拟内存空间的起始位置和结束位置,描述的是一个合理的地址空间范围(即严格确保 vm_start < vm_end的关系);
list_link是一个双向链表,按照从小到大的顺序把一系列用
vma_struct表示的虚拟内存空间链接起来,并且还要求这些链起来的
vma_struct应该是不相交的,即vma之间的地址空间无交集;
vm_flags表示了这个虚拟内存空间的属性,目前的属性包括
#define VM_READ 0x00000001 //只读 #define VM_WRITE 0x00000002 //可读写 #define VM_EXEC 0x00000004 //可执行
vm_mm是一个指针,指向一个比
vma_struct更高的抽象层次的数据结构
mm_struct
这个数据结构表示了包含所有虚拟内存空间的共同属性。
mm_struct
struct mm_struct { // linear list link which sorted by start addr of vma list_entry_t mmap_list; // current accessed vma, used for speed purpose struct vma_struct *mmap_cache; 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 };
mmap_list是双向链表头,链接了所有属于同一页目录表的虚拟内存空间
mmap_cache是指向当前正在使用的虚拟内存空间
pgdir所指向的就是
mm_struct数据结构所维护的页表
map_count记录
mmap_list里面链接的
vma_struct的个数
sm_priv指向用来链接记录页访问情况的链表头
结构关系
代码补充
do_pgfault
首先看下注释/*LAB3 EXERCISE 1: YOUR CODE * Maybe you want help comment, BELOW comments can help you finish the code * * Some Useful MACROs and DEFINEs, you can use them in below implementation. * MACROs or Functions: * get_pte : get an pte and return the kernel virtual address of this pte for la * if the PT contians this pte didn't exist, alloc a page for PT (notice the 3th parameter '1') * pgdir_alloc_page : call alloc_page & page_insert functions to allocate a page size memory & setup * an addr map pa<--->la with linear address la and the PDT pgdir * DEFINES: * VM_WRITE : If vma->vm_flags & VM_WRITE == 1/0, then the vma is writable/non writable * PTE_W 0x002 // page table/directory entry flags bit : Writeable * PTE_U 0x004 // page table/directory entry flags bit : User can access * VARIABLES: * mm->pgdir : the PDT of these vma * */ (1) try to find a pte, if pte's PT(Page Table) isn't existed, then create a PT. (2) if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr
相关定义
根据注释修改代码
if (ptep == NULL) { cprintf("get_pte in do_pgfault failed\n"); goto failed; } // if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr //页表不存在 if (*ptep == 0) { //尝试分配一空闲页,匹配物理地址与逻辑地址,建立对应关系 if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) {//失败内存不够退出 cprintf("pgdir_alloc_page in do_pgfault failed\n"); goto failed; } }
练习2
补充完成基于FIFO的页面替换算法(需要编程)
完成
vmm.c中的
do_pgfault函数,并且在实现
FIFO算法的
swap_fifo.c中完成
map_swappable和
swap_out_victim函数。通过对swap的测试
分析
根据练习1,当页错误异常发生时,有可能是因为页面保存在swap区或者磁盘文件上造成的,所以我们需要利用页面替换算法解决这个问题。页面替换主要分为两个方面,页面换出和页面换入。
- 页面换入主要在上述的
do_pgfault()函数实现;
- 页面换出主要在
swap_out_vistim()函数实现。
在换入时,需要先检查产生访问异常的地址是否属于某个VMA表示的合法虚拟地址,并且保存在硬盘的swap文件中(即对应的PTE的高24位不为0,而最低位为0),则是执行页换入的时机,将调用swap_in函数完成页面换入。
在换出时,采取的是消极的换出策略,是在调用alloc_pages函数获取空闲页时,此函数如果发现无法从物理内存页分配器(比如First Fit)获得空闲页,就会进一步调用swap_out函数 换出某页,实现一种消极的换出策略
相关定义
代码
do_pgfault
查看注释/*LAB3 EXERCISE 2: YOUR CODE * Now we think this pte is a swap entry, we should load data from disk to a page with phy addr, * and map the phy addr with logical addr, trigger swap manager to record the access situation of this page. * * Some Useful MACROs and DEFINEs, you can use them in below implementation. * MACROs or Functions: * swap_in(mm, addr, &page) : alloc a memory page, then according to the swap entry in PTE for addr, * find the addr of disk page, read the content of disk page into this memroy page * page_insert : build the map of phy addr of an Page with the linear addr la * swap_map_swappable : set the page swappable */
根据注释补充代码
else { // if this pte is a swap entry, then load data from disk to a page with phy addr // and call page_insert to map the phy addr with logical addr if(swap_init_ok) {//页表项非空,根据mm结构和addr地址,尝试将硬盘中的内容换入page中 struct Page *page=NULL; ret = swap_in(mm, addr, &page); if (ret != 0) { cprintf("swap_in in do_pgfault failed\n"); goto failed; } //建立虚拟地址和物理地址之间的对应关系 page_insert(mm->pgdir, page, addr, perm); //将此页面设置为可交换 swap_map_swappable(mm, addr, page, 1); page->pra_vaddr = addr; } else { cprintf("no swap_init_ok but ptep is %x, failed\n",*ptep); goto failed; } }
_fifo_map_swappable()
首先是_fifo_map_swappable,可用于建立页访问属性和关系,比如访问时间的先后顺序。
首先看下注释
//record the page access situlation /*LAB3 EXERCISE 2: YOUR CODE*/ //(1)link the most recent arrival page at the back of the pra_list_head qeueue.
根据注释写代码
/*
* (3)_fifo_map_swappable: According FIFO PRA, we should link the most recent arrival page at the back of pra_list_head qeueue
*/
static int
_fifo_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in)
{
list_entry_t *head=(list_entry_t*) mm->sm_priv;
list_entry_t *entry=&(page->pra_page_link);
assert(entry != NULL && head != NULL);
//record the page access situlation /*LAB3 EXERCISE 2: YOUR CODE*/ //(1)link the most recent arrival page at the back of the pra_list_head qeueue.//将最近用到的页面添加到次序的队尾
list_add(head, entry);
return 0;
}
_fifo_swap_out_victim()
然后是_fifo_swap_out_victim,可用于实现挑选出要换出的页。
查看下注释
/* Select the victim */ /*LAB3 EXERCISE 2: YOUR CODE*/ //(1) unlink the earliest arrival page in front of pra_list_head qeueue //(2) set the addr of addr of this page to ptr_page
根据注释写代码
/* * (4)_fifo_swap_out_victim: According FIFO PRA, we should unlink the earliest arrival page in front of pra_list_head qeueue, * then set the addr of addr of this page to ptr_page. */ static int _fifo_swap_out_victim(struct mm_struct *mm, struct Page ** ptr_page, int in_tick) { list_entry_t *head=(list_entry_t*) mm->sm_priv; assert(head != NULL); assert(in_tick==0); /* Select the victim */ /*LAB3 EXERCISE 2: YOUR CODE*/ //(1) unlink the earliest arrival page in front of pra_list_head qeueue //(2) set the addr of addr of this page to ptr_page /* Select the tail */ //指出需要被换出的页 list_entry_t *le = head->prev; assert(head != le); //le2page 宏可以根据链表元素,获得对应page的指针 struct Page *p = le2page(le, pra_page_link); //将进来最早的页面从队列中删除 list_del(le); assert(p != NULL); //将这一页的地址存储在ptr_page中 *ptr_page = p; return 0; }
运行结果
运行成功
收获
通过本次实验,我了解物理内存管理中的连续空间分配算法的具体实现,熟悉掌握Page Fault异常处理和FIFO页替换算法的实现。对页面替换机制有了一个大题的了解,在试验中学习,收获较多。但还是对执行流程较为模糊,对页替换算法还是掌握不牢,需要进一步的巩固学习.相关文章推荐
- 操作系统ucore lab3实验报告
- 操作系统ucore lab7实验报告
- 操作系统实验报告:ucore-lab1
- 操作系统是如何工作的--知识总结及实验报告
- 操作系统实验报告
- 操作系统ucore lab2实验报告
- 操作系统存储管理实验课程设计报告
- 操作系统文件系统设计实验报告
- ucore操作系统lab7——实验报告
- 操作系统ucore lab8实验报告
- 操作系统实验报告
- 操作系统ucore lab6实验报告
- 操作系统实验报告 lab8
- 操作系统实验报告 lab3
- 操作系统实验报告:仅能输出helloworld的最小系统
- 操作系统ucore lab2实验报告
- 操作系统ucore lab7实验报告
- 操作系统ucore lab1实验报告
- 操作系统实验报告 lab6
- # 操作系统实验报告:ucore-lab1