清华大学操作系统-物理内存管理实验报告

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

练习0:把实验1的代码填入本实验中代码有lab1的注释相应的部分。用understand中的merge工具将实验1中填写代码部分复制到实验2中,如图1。图1练习1:实现firstfit连续物理内存分配算法。对于lab2代码首先对其make,之后在虚拟机中运行查看其错误所在位置如图2。可以发现其错误出现在default_check(void)这个函数之中,该函数为检查firstfit算法的函数。继续分析错误出现的原因:structPage*p0=alloc_pages(5),*p1,*p2;assert(p0!=NULL);assert(!PageProperty(p0));list_entry_tfree_list_store=free_list;list_init(&free_list);assert(list_empty(&free_list));assert(alloc_page()==NULL);unsignedintnr_free_store=nr_free;nr_free=0;free_pages(p0+2,3);assert(alloc_pages(4)==NULL);assert(PageProperty(p0+2)&&p0[2].property==3);assert((p1=alloc_pages(3))!=NULL);assert(alloc_page()==NULL);assert(p0+2==p1);p2=p0+1;free_page(p0);free_pages(p1,3);assert(PageProperty(p0)&&p0-property==1);assert(PageProperty(p1)&&p1-property==3);assert((p0=alloc_page())==p2-1);//错误出现的位置分析源码后可知,在其对内存进行一些列分配释放操作后,再次申请一页内存后出现错误,可知其在最后一次p0=alloc_page()申请中得到内存页的位置与算法规则不相符,回到default_alloc_pages(size_tn)、default_free_pages(structPage*base,size_tn)函数中可以分析得到,在分配函数和释放函数中都出现错误:list_add(&free_list,&(p-page_link));分配函数中若分得的块大小大于申请页数,则需要将多余的页形成一个块,按照从低地址到高地址的顺序挂回free_list中,而不是直接挂到free_list的后面。list_add(&free_list,&(base-page_link));将释放页与空闲页合并操作之后,只是将新的空闲区域挂到了free_list的后面,并没有按照从低地址到高地址的顺序将其挂到free_list之中,导致后面check函数中出现错误。对源代码做如下修改(红色为修改部分):staticstructPage*default_alloc_pages(size_tn){assert(n0);//出错判断if(nnr_free){//申请页大小与现有空闲页比较returnNULL;}structPage*page=NULL;list_entry_t*le=&free_list;while((le=list_next(le))!=&free_list){//从free_list的头开始寻找符合条件的空闲块structPage*p=le2page(le,page_link);if(p-property=n){page=p;break;}}if(page!=NULL){list_del(&(page-page_link));if(page-propertyn){//若分配成功的块总页数比申请页数大structPage*p=page+n;p-property=page-property-n;list_add(list_prev(le),&(p-page_link));}nr_free-=n;ClearPageProperty(page);}returnpage;}释放内存与申请内存思路大致相同:default_free_pages(structPage*base,size_tn){intflag=0;//设置标志位assert(n0);structPage*p=base;for(;p!=base+n;p++){assert(!PageReserved(p)&&!PageProperty(p));p-flags=0;set_page_ref(p,0);}base-property=n;SetPageProperty(base);list_entry_t*le=list_next(&free_list);while(le!=&free_list){p=le2page(le,page_link);le=list_next(le);if(base+base-property==p){base-property+=p-property;ClearPageProperty(p);list_del(&(p-page_link));}elseif(p+p-property==base){p-property+=base-property;ClearPageProperty(base);base=p;list_del(&(p-page_link));}}nr_free+=n;le=list_next(&free_list);while(le!=&free_list){p=le2page(le,page_link);le=list_next(le);structPage*q=le2page(le,page_link);if(pbase){//判断插入位置在头部list_add(&free_list,&(base-page_link));flag=1;break;}if(pbase&baseq){//判断插入位置在中间list_add_before(le,&(base-page_link));flag=1;break;}}//判断插入位置在尾部if(flag==0)list_add_before(&free_list,&(base-page_link));}修改思路:将合并后的空闲页按照从低到高的地址顺序插入到free_list之中,注意边界条件。修改后再次运行代码如图3:图3可以看到check_alloc_page()succeeded,修改成功,分配函数成功运行。Lab2中的分配代码、释放代码都是以空闲块为一个整体单位,此外在labcode_result中分配与释放都是以页为单位,将所有的空闲页按照从低地址到高地址全部挂到free_list上。分析上述两种方式,我认为第一种方式更加合理。将所有的空闲页全部挂到free_list链表上开销过大,同时在进行分配时需要将符合条件区域内的所有页进行操作,但是在以块为单位的算法中,只需要将每一块的第一页作为该块的代表挂到free_list上即可,方便操作同时减少开销。练习2:实现寻找虚拟地址对应的页表项pde_t*pdep=&pgdir[PDX(la)];if(!(*pdep&PTE_P)){//如果不存在structPage*page;if(!create||(page=alloc_page())==NULL){//判断是否建立returnNULL;}//设置参数,初始化set_page_ref(page,1);uintptr_tpa=page2pa(page);memset(KADDR(pa),0,PGSIZE);*pdep=pa|PTE_U|PTE_W|PTE_P;}return&((pte_t*)KADDR(PDE_ADDR(*pdep)))[PTX(la)];//返回入口练习3:释放某虚拟地址所在的页并取消对应的二级页表项的映射if(*ptep&PTE_P){//判断是否存在structPage*page=pte2page(*ptep);if(page_ref_dec(page)==0){//判断是否需要释放free_page(page);}*ptep=0;//初始化二级页表项tlb_invalidate(pgdir,la);//更新tlb}

1 / 5
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功