操作系统JOS实习第二次报告

虚拟内存有什么用  时间:2021-01-16  阅读:()

张弛00848231,zhangchitc@gmail.
comMay30,2011Contents1Introduction22PhysicalPageManagement22.
1Physicalpageanditsdatastructure22.
2Physicalmemorylayout43VirtualMemory93.
1Virtual,Linear,andPhysicalAddresses103.
2Referencecounting103.
3PageTableManagement134KernelAddressSpace204.
1PermissionsandFaultIsolation204.
2InitializingtheKernelAddressSpace204.
3AddressSpaceLayoutAlternatives231操作系统实习报告张弛,008482311Introduction我在实验中主要参考了华中科技大学邵志远老师写的JOS实习指导,在邵老师的主页上http://grid.
hust.
edu.
cn/zyshao/OSEngineering.
htm可以找到.
但是这次实验的指导远远不如lab1的指导详尽,所以我这里需要补充的内容会很多.
2PhysicalPageManagementExercise1.
Inthefilekern/pmap.
c,youmustimplementcodeforthefollowingfunctions.
boot_alloc()page_init()page_alloc()page_free()Youalsoneedtoaddsomecodetoi386_vm_init()inpmap.
c,asindicatedbycommentsthere.
Fornow,justaddthecodeneededleadinguptothecalltocheck_page_alloc().
Youprobablywanttoworkonboot_alloc(),theni386_vm_init(),thenpage_init(),page_alloc(),andpage_free().
check_page_alloc()testsyourphysicalpageallocator.
YoushouldbootJOSandseewhethercheck_page_alloc()reportssuccess.
Fixyourcodesothatitpasses.
Youmayfindithelpfultoaddyourownassert()stoverifythatyourassumptionsarecorrect.
这部分实验的内容暂时和页面转换机制没有关系,我们需要重点关注的是物理页面的规划以及管理.
主要需要关注JOS内核代码中的inc/queue.
h文件以及kern/pmap.
c文件.
2.
1Physicalpageanditsdatastructure请仔细阅读邵老师的讲义中4.
3章第一节页面管理.
其中重点需要掌握以下内容:1.
物理页和Page数据结构的对应关系2.
对Page*页面链表的宏操作,在inc/queue.
h中里面我唯一碰到的问题就是没看懂为什么JOS给出的链表模板要写成下面这样的形式:inc/queue.
h§¤165/*166*Resetthelistnamed"head"totheemptylist.
2操作系统实习报告张弛,00848231167*/168#defineLIST_INIT(head)do{\169LIST_FIRST((head))=NULL;\170}while(0)这个宏的的目的是将链表初始化为空.
但我奇怪的是为什么要写成一个只执行一次的while循环的形式,而不是直接大括号包住这一段语句就可以了实验室的白光东师兄给出了一个详尽满意的答案.
他给了我下面这样的程序:test.
c§¤1#include23#defineMACRO()do{\4printf("hello\n");\5}while(0)67intmain(){8intx;9scanf("%d\n",&x);1011if(x)12MACRO();13else14printf("thisiselse\n");15return0;16}然后使用gcc-Etest.
c编译这段程序,参数E的目的是为了让编译器仅仅进行预编译以后即停下来,并输出预编译后的程序结果,那么我们得到这样的输出intmain(){intx;scanf("%d\n",&x);if(x)do{printf("hello\n");}while(0);elseprintf("thisiselse\n");return0;}zhangchi@zhangchi-desktop:/tmp/test$很明显我们看到相关的MACRO();调用变成了其相应的宏展开,请特别注意,调用的时候我们是以单个语句的形式调用MACRO()的,那么展开以后的形式还是满足了单个语句(一个while循环),并且,在其后面加上了分号.
如果我们把MACRO改成:test.
c§¤1#defineMACRO(){\2printf("hello\n");\3}那么再次展开的结果会变成:intmain(){intx;3操作系统实习报告张弛,00848231scanf("%d\n",&x);if(x){printf("hello\n");};elseprintf("thisiselse\n");return0;}zhangchi@zhangchi-desktop:/tmp/test$明显可以看出这样的转换造成语法错误,用大括号包裹的代码块后不需要分号.
这里出错的原因就在于我们调用MACRO()之前是当成一个单个语句,调用展开后变成了一个代码块.
那么相应的语法结构就出现了变化导致出错.

真是考虑得非常细致!
感谢师兄!
2.
2Physicalmemorylayout请仔细阅读邵老师的讲义中的4.
3章第一节页面管理中"页面管理链表在内存中的存储和放置"小节.
重点理解1.
pages数组和Page*链表的对应关系2.
pages所在的空间是怎样分配的3.
整个物理内存的布局这里要说的是,在做完lab1以后,我们知道了在实模式下物理页面前640KB的一些分配情况,如BIOS的载入地址、bootloader载入地址、操作系统内核ELF文件头的临时存放空间等等,具体的布局应该如下图所示:在lab1完成后,我们从0x000100000这个位置放入内核,直到end结束.
end是链接器作链接时得到的内核结束地址.
那么在建立物理页面对应的Page*链表时,我们需要为这个链表分配实际的物理内存空间,在二级页地址映射机制中,系统还需要一个页目录存下所有二级页表的地址,这个也是需要操作系统预先分配空间的,所以结合上图,我们第一步完成之后物理内存布局应该如下图所示:4操作系统实习报告张弛,00848231我们第一步的目的就是为页目录和pages分配好空间,并建立起空闲页表pagefreelist.
开始写代码的时候,首先需要弄清楚kern/pmap.
c中的几个基本的变量:kern/pmap.
c§¤12//Thesevariablesaresetbyi386_detect_memory()13staticphysaddr_tmaxpa;//Maximumphysicaladdress14size_tnpage;//Amountofphysicalmemory(inpages)15staticsize_tbasemem;//Amountofbasememory(inbytes)16staticsize_textmem;//Amountofextendedmemory(inbytes)1718//Thesevariablesaresetini386_vm_init()19pde_t*boot_pgdir;//Virtualaddressofboottimepagedirectory20physaddr_tboot_cr3;//Physicaladdressofboottimepagedirectory21staticchar*boot_freemem;//Pointertonextbyteoffreemem2223structPage*pages;//Virtualaddressofphysicalpagearray24staticstructPage_listpage_free_list;//Freelistofphysicalpages这里只需要知道两个变量,bootfreemem和bootpgdir,前者是当前可用内存的开始地址(也就是说,内核载入以后,系统管理所需要的内容就从end以后开始分配,即从一开始bootfreemem是等于end,这个在接下来的代码里就能看到);bootpgdir则是系统页目录所在空间的开始地址.
注注注意意意,,,两两两者者者地地地址址址都都都是是是虚虚虚拟拟拟地地地址址址!
!
!
在在在这这这次次次lab中中中一一一定定定要要要搞搞搞清清清楚楚楚的的的一一一个个个细细细节节节就就就是是是虚虚虚拟拟拟地地地址址址,,,线线线性性性地地地址址址和和和物物物理理理地地地址址址的的的区区区别别别,,,以以以及及及我我我们们们使使使用用用的的的地地地址址址变变变量量量哪哪哪些些些是是是虚虚虚拟拟拟地地地址址址,,,哪哪哪些些些是是是物物物理理理地地地址址址.
.
.
接下来我们可以看到i386vminit(),从这里开始我们这次的lab.
一开始就看到关于页目录的初始化代码:kern/pmap.
c:i386vminit()§¤12//createinitialpagedirectory.
3pgdir=boot_alloc(PGSIZE,PGSIZE);45memset(pgdir,0,PGSIZE);6boot_pgdir=pgdir;7boot_cr3=PADDR(pgdir);5操作系统实习报告张弛,00848231其中bootalloc()为其分配内存空间地址,然后将分配的地址段清空.
然后将其物理地址(PADDR)放入bootcr3准备启动x86的页面地址转换机制.
这里要注意几点:PGSIZE为一个物理页的大小4KB=4096B,定义在inc/mmu.
h中,其中还有我们后面要用的重要常量PTSIZE,为一个页表对应实际物理内存的大小,即1024*4KB=4MB从bootalloc()得到的页面是不会作相应的初始化工作的,所以如果对分配到的空间有要求清空,必须自己亲自动手memset接受的清空地址是pgdir即一个虚拟地址,这个在我们后面的工作中对实际分配到的物物物理理理页页页面面面进行初始化时提醒,清空时使用memset也一定要使用实际物理页面对应的内内内核核核虚虚虚拟拟拟地地地址址址bootcr3得到的是一个物物物理理理地地地址址址,这个和我们前面强调的分清每个地址变量到底是虚拟地址还是物理地址有密切联系接下来我们来看一下第一个需要实现的函数bootalloc()kern/pmap.
c:bootalloc()§¤1staticvoid*2boot_alloc(uint32_tn,uint32_talign)3{4externcharend[];5void*v;67//Initializeboot_freememifthisisthefirsttime.
8//'end'isamagicsymbolautomaticallygeneratedbythelinker,9//whichpointstotheendofthekernel'sbsssegment-10//i.
e.
,thefirstvirtualaddressthatthelinker11//did_not_assigntoanykernelcodeorglobalvariables.
12if(boot_freemem==0)13boot_freemem=end;1415//LAB2:Yourcodehere:16//Step1:roundboot_freememuptobealignedproperly17//(hint:lookintypes.
hforsomehandymacros)18//Step2:savecurrentvalueofboot_freememasallocatedchunk19//Step3:increaseboot_freememtorecordallocation20//Step4:returnallocatedchunk2122v=ROUNDUP(boot_freemem,align);23boot_freemem=(char*)v+n;2425returnv;26}这个函数的问题不大.
看接下来的代码:kern/pmap.
c:i386vminit()§¤12//RecursivelyinsertPDinitselfasapagetable,toform3//avirtualpagetableatvirtualaddressVPT.
6操作系统实习报告张弛,008482314//(Fornow,youdon'thaveunderstandthegreaterpurposeofthe5//followingtwolines.
)67//Permissions:kernelRW,userNONE8pgdir[PDX(VPT)]=PADDR(pgdir)|PTE_W|PTE_P;910//sameforUVPT11//Permissions:kernelR,userR12pgdir[PDX(UVPT)]=PADDR(pgdir)|PTE_U|PTE_P;131415//Allocateanarrayofnpage'structPage'sandstoreitin'pages'.
16//Thekernelusesthisarraytokeeptrackofphysicalpages:for17//eachphysicalpage,thereisacorrespondingstructPageinthis18//array.
'npage'isthenumberofphysicalpagesinmemory.
19//User-levelprogramswillgetread-onlyaccesstothearrayaswell.
20//Yourcodegoeshere:212223pages=boot_alloc(npage*sizeof(structPage),PGSIZE);242526//Nowthatwe'veallocatedtheinitialkerneldatastructures,weset27//upthelistoffreephysicalpages.
Oncewe'vedoneso,allfurther28//memorymanagementwillgothroughthepage_*functions.
In29//particular,wecannowmapmemoryusingboot_map_segmentorpage_insert30page_init();3132check_page_alloc();3334page_check();前两句对pgdir的操作我们可以先不用管他,在后来设置页表的时候我们会回过头来看这两句话的含义.
在23行里为pages分配空间以后,就进入倒pageinit()对链表进行初始化了.
在进行接下来的编码之前,我们先需要了解JOS对于地址编码的一些规定,在inc/mmu.
h中,我们可以找到一组详尽的宏:inc/mmu.
h§¤16//Alinearaddress'la'hasathree-partstructureasfollows:17//1810-10-12-19//|PageDirectory|PageTable|OffsetwithinPage|20//|Index|Index||2122//\---PDX(la)PTX(la)PGOFF(la)----/23PPN(la)24//25//ThePDX,PTX,PGOFF,andPPNmacrosdecomposelinearaddressesasshown.
26//ToconstructalinearaddresslafromPDX(la),PTX(la),andPGOFF(la),27//usePGADDR(PDX(la),PTX(la),PGOFF(la)).
2829//pagenumberfieldofaddress30#definePPN(la)(((uintptr_t)(la))>>PTXSHIFT)31#defineVPN(la)PPN(la)//usedtoindexintovpt[]3233//pagedirectoryindex34#definePDX(la)((((uintptr_t)(la))>>PDXSHIFT)&0x3FF)35#defineVPD(la)PDX(la)//usedtoindexintovpd[]3637//pagetableindex38#definePTX(la)((((uintptr_t)(la))>>PTXSHIFT)&0x3FF)397操作系统实习报告张弛,0084823140//offsetinpage41#definePGOFF(la)(((uintptr_t)(la))&0xFFF)4243//constructlinearaddressfromindexesandoffset44#definePGADDR(d,t,o)((void*)((d)=npage)79panic("pa2pagecalledwithinvalidpa");80return&pages[PPN(pa)];81}8283staticinlinevoid*84page2kva(structPage*pp)85{86returnKADDR(page2pa(pp));87}我们知道每个物理页面对应一个Page的struct和一个物理页号PPN和唯一的物理首地址,这组宏就是作这几个量之间的对应关系的,其中:一个Page对应的PPN就是page2ppn(structPage),而一个PPN对应的structPage则是pages[PPN]一个Page对应的物理地址是page2pa(structPage),而一个物理地址对应的structPage则是pa2page(pa)最后还提供了一个页面到内核虚拟地址的转换宏page2kva,这个也很好用.
根据Exercise的提示,我们先来看看要填写的第一个函数pgdirwalk()kern/pmap.
c:pgdirwalk()§¤14操作系统实习报告张弛,008482311pte_t*2pgdir_walk(pde_t*pgdir,constvoid*va,intcreate)3{4pde_t*pt=pgdir+PDX(va);5void*pt_kva;67if(*pt&PTE_P){8pt_kva=(void*)KADDR(PTE_ADDR(*pt));9return(pte_t*)pt_kva+PTX(va);10}1112structPage*newpt;1314if(create==1&&page_alloc(&newpt)==0){1516memset(page2kva(newpt),0,PGSIZE);17newpt->pp_ref=1;1819*pt=PADDR(page2kva(newpt))|PTE_U|PTE_W|PTE_P;20pt_kva=(void*)KADDR(PTE_ADDR(*pt));21return(pte_t*)pt_kva+PTX(va);22}2324returnNULL;25}简单说一下这个函数的作用,其实这个函数就是实现虚拟地址到实际物理地址的翻译过程.
根据给出的虚拟地址,返回其二级页表中对应的页表项.
根据参数create的值,如果等于1,则如果虚拟地址还没有对应的物理页面,则分配一个给它.
代码中有几个地方需要注意:1.
第7行代码:判断页目录中va对应二级页表是否存在应该看页目录的对应PDX(va)项最后一位状态位present是否为0,我一开始写成了if(*pt!
=0)了,这样显然不对2.
第16行代码:一定记得memset参数使用的是内核虚拟地址3.
第19行代码:这里我们为新建的物理页设置页目录表项时,页目录后12位的权限位为什么是PTEU|PTEW|PTEP呢第三条提出的问题在注释中其实已经提示了,但是我还是查询了Intelx86的手册:在Reference里的IA-32IntelArchitectureSoftwareDeveloper'sManuals,其中的Volume3A:SystemProgrammingGuide,Part1.
在里面的COMBININGPAGEANDSEGMENTPROTECTION一节里,提到了分段分页保护机制的实现.
当一个程序试图访问一个虚拟地址的数据时,x86系统的保护机制运行为:先检查段权限位DPL,这个是所访问数据段或者Callgate的权限级别,和当前权限级别CPL进行比较,如果不够则产生权限异常(具体机制请参考手册,在这个问题上我们不用管它),否则进入下一步再检查页目录相应表项的访问权限,如果不够也产生异常15操作系统实习报告张弛,00848231最后检查二级页表相应表项的访问权限,不够就产生异常可以看到,在任意一次检查上违例了,那么访问失效.
实际上我们知道页目录中一个表项代表的就是内存中的1024个物理页,这些页中很可能对访问的控制各不相同,比如有的可以给用户写权限,有的只能读,有的连读都不行.
那么在无法提前知道这些需求的话,最明智的办法就是不在页目录这一环节限制太多,让最终的访问控制在二级页表这一环节上再去具体设置.
实际上Intel手册上给出了一个页目录加页表的访问控制的组合控制效果:这个图应该是很容易看明白的,只有一个不太清楚的地方,就是为什么当最终组合效果的权限要求是内核态时,读写权限全部是可读也可写的助教告诉我,因为在内核态下,内核想要写入任意地址都是可行的.
即便内核在写入一个表项时发现该页表项权限只能允许它读的话,通过修改CR0.
WP寄存器,内核也能最终写入这个地址,所以访问类型就显得没有意义了,感谢张顺廷师兄的解释!
!
接下来看看要填的第二个函数bootmapsegment():kern/pmap.
c:bootmapsegment()§¤1staticvoid2boot_map_segment(pde_t*pgdir,uintptr_tla,size_tsize,physaddr_tpa,intperm)16操作系统实习报告张弛,008482313{4intoffset;5pte_t*pte;67for(offset=0;offsetpp_ref--;14}else{15page_remove(pgdir,va);16}17}1819*pte=page2pa(pp)|perm|PTE_P;20pp->pp_ref++;2122return0;23}这个函数负责将一个虚拟地址映射到它实际对应的物理页面上去,这里有几种调用的情况:1.
这个虚拟地址所在地址在二级页表上没有挂载页面,那么这时直接修改相应的二级页表表项即可2.
如果已经挂载了页面,且页面和当前分配的物理页面不一样,那么就卸下原来的页面,再挂载新的页面.
3.
如果已经挂载了页面,而且已挂载页面和当前分配的物理页面是同样的,这是什么情况呢这种情况非常普遍,就是当内核要修改一个页面的访问权限时,它会将同一个页面重新插入一次,传入不同的perm参数,即完成了权限修改.

A400互联(49元/月)洛杉矶CN2 GIA+BGP、1Gbps带宽,全场独服永久5折优惠

a400互联是一家成立于2020年商家,主营美国机房的产品,包括BGP线路、CN2 GIA线路的云服务器、独立服务器、高防服务器,接入线路优质,延迟低,稳定性高,额外也还有香港云服务器业务。当前,全场服务器5折,香港VPS7折,洛杉矶VPS5折,限时促销!A400互联官网:https://a400.net/优惠活动全场独服永久5折优惠(续费同价):0722香港VPS七折优惠:0711洛杉矶VPS五...

ZJI全新上架香港站群服务器,4C段238个IP月付1400元起

ZJI本月新上线了香港葵湾机房站群服务器,提供4个C段238个IPv4,支持使用8折优惠码,优惠后最低每月1400元起。ZJI是原Wordpress圈知名主机商家:维翔主机,成立于2011年,2018年9月更名为ZJI,提供中国香港、台湾、日本、美国独立服务器(自营/数据中心直营)租用及VDS、虚拟主机空间、域名注册等业务,所选数据中心均为国内普遍访问速度不错的机房。葵湾二型(4C站群)CPU:I...

DiyVM:50元/月起-双核,2G内存,50G硬盘,香港/日本/洛杉矶机房

DiyVM是一家比较低调的国人主机商,成立于2009年,提供VPS主机和独立服务器租用等产品,其中VPS基于XEN(HVM)架构,数据中心包括香港沙田、美国洛杉矶和日本大阪等,CN2或者直连线路,支持异地备份与自定义镜像,可提供内网IP。本月商家最高提供5折优惠码,优惠后香港沙田CN2线路VPS最低2GB内存套餐每月仅50元起。香港(CN2)VPSCPU:2cores内存:2GB硬盘:50GB/R...

虚拟内存有什么用为你推荐
云主机租用云主机服务器租用费用怎么算虚拟空间购买怎样购买顶级域名和虚拟主机空间400M主机租用电脑租赁多少钱一天呢?有人租过吗?linux虚拟主机linux下最好的虚拟机是什么呢 VMware 还是virtualbox中国互联网域名注册负责我国境内internet用户域名注册是什么机构asp主机请问虚似主机和Asp服务器软件都是一个意思吗海外域名怎样注册国外域名?php虚拟空间我已经有一套网站php代码和模板,并且有自己的虚拟空间和域名,怎么才能把我的代码加入到网站上.虚拟主机管理系统我也想和你学虚拟主机管理系统的操作上海虚拟主机我想购买虚拟主机,选个品牌。大家给点意见。电信为主。当然肯定要支持多线。
网站虚拟主机空间 最新代理服务器地址 鲨鱼机 免备案空间 godaddy域名转出 php探针 免费ftp空间申请 湖南服务器托管 毫秒英文 seednet 共享主机 贵阳电信 万网空间 云销售系统 xshell5注册码 香港ip cdn加速技术 reboot cc加速器 linuxvi 更多