lab2

本文探讨了操作系统中内存管理的基本原理,特别是页表机制的实现细节。包括页表项的分配与释放、页表项查找、物理页的映射等关键操作。并通过具体函数解释了如何在内存中建立有效的映射。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Part1 

Exercise 1:
 boot_alloc: 

    if(!n){
		result=nextfree;
		return result;
    	}
	else{
		  uint32_t remainingPages=npages-((uint32_t)nextfree-(uint32_t)KERNBASE)/PGSIZE;
		  if(n<remainingPages*PGSIZE){
		  	 result=nextfree;
			 nextfree=ROUNDUP(nextfree+n,PGSIZE);
			 return result;
		  	}else{
		  	 panic("The memory has been used up\n");
			 
		  	}
		
		}
	return NULL;
mem_init:
  pages=(struct PageInfo *)boot_alloc(npages*sizeof(struct PageInfo));
	memset(pages,0,npages*sizeof(struct PageInfo));
Page_init:
size_t i;
	uint32_t j=((uint32_t)boot_alloc(0)-KERNBASE)/PGSIZE;
	uint32_t j2=IOPHYSMEM/PGSIZE;
	for (i = npages-1; i>=1; i--) {
		//the physical memory pages that has been used by pages and kernel 
		
		//cprintf("rrrrrrrrrrrrrrrrr");
		if(!((i>=j2&&i<j)||i==0)){
			pages[i].pp_ref = 0;
			pages[i].pp_link = page_free_list;
			page_free_list = &pages[i];
		}
	}

Page_alloc:
if(page_free_list==NULL) return 0;
    struct PageInfo *result=page_free_list;
	page_free_list=page_free_list->pp_link;

	//set '\0'
	if(alloc_flags&ALLOC_ZERO){
	void * resultKVA=page2kva(result);
	memset(resultKVA,0,PGSIZE);
	}
	//cprintf("page_alloc va is %08x\n",page2kva(result));
	return result;

Page_free:
if(pp->pp_ref!=0) return;
	pp->pp_link=page_free_list;
	page_free_list=pp;

Part2 


Exercise 3:
   ctrl+a c进入qemu调试
   qemu下调试: xp/Nx physical address与GDB调试的x/Nxw virtual address,查看内存的内容
   info pg和info mem显示内存映射的情况

Question1: 虚拟地址。2013.7.17
Exercise 4:

pte_t *
pgdir_walk(pde_t *pgdir, const void *va, int create)
{
	// Fill this function in
	pte_t ptet=pgdir[PDX(va)];
	//cprintf("cprintf_walk, the pgdir is %08x\n",ptet);
	if((ptet&PTE_P)==0){
		 if(create==false)return NULL;
		 struct PageInfo *pageinfo=page_alloc(1);
		 if(!pageinfo) return NULL;
		 pageinfo->pp_ref++;
		 pgdir[PDX(va)]=page2pa(pageinfo)| PTE_U | PTE_P|PTE_W;
		// cprintf("pgdir_walk, the physical is %08x va is %08x %08x\n",PTX(va),va,page2kva(pageinfo)+PTX(va));
		 return (pte_t*)page2kva(pageinfo)+PTX(va);
	}
	pte_t * ptet_va=KADDR(PTE_ADDR(ptet));
	//cprintf("pdgidr_walk page table item is %08x\n",ptet_va[PTX(va)]);
    return ptet_va+PTX(va);
}
static void
boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
{
	// Fill this function in
	// i think the va and pa must be a multiple of PGSIZE also Author:ryz
	// if size is more than 4M, one pte can't contain so may datas???!!!!!
	// use walk every va address, there is no any problem
	
	if(size&0xFFF) panic("boot_map_region: va is not a multiple of PGSIZE %08x\n",size);
	uintptr_t i;
	for(i=0;i<size;i+=PGSIZE){
		pte_t * ptet=pgdir_walk(pgdir,(void *)va,true);
		*ptet=pa|PTE_P|perm;
		pa+=PGSIZE;
		va+=PGSIZE;			
	}
}
struct PageInfo *
page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
{
	// Fill this function in
	pte_t * ptet=pgdir_walk(pgdir,va,false);
	if(*pte_store!=NULL)*pte_store=ptet;
	if((ptet==NULL)||((*ptet&PTE_P)==0)) return NULL;
	//cprintf("page_lookup linear address is %08x\n",(uint32_t)va);
	//cprintf("11111111111111\n");
	//cprintf("%08x\n",*ptet);
	return pa2page(PTE_ADDR(*ptet));
	//cprintf("22222222222222222\n");
	
}
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	//cprintf("page_remove entry\n");
	pte_t *ptet;
	struct PageInfo *pageinfo=page_lookup(pgdir,va,&ptet);
	//cprintf("333333333333");
	if (pageinfo==NULL) return;
	page_decref(pageinfo);
	*ptet=0;
	tlb_invalidate(pgdir,va);
}
int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{
	// Fill this function in
	//cprintf("page_insert entry\n");
	//cprintf("page_insert the va is %08x\n",(uint32_t)va);
	pte_t * ptet=pgdir_walk(pgdir,va,true);
	if(ptet==NULL) return -E_NO_MEM;
	if(*ptet&PTE_P){
		if(PTE_ADDR(*ptet)==page2pa(pp)){
			*ptet=page2pa(pp)|perm|PTE_P;
			tlb_invalidate(pgdir, va);
			//cprintf("page_insert linear address is %08x, the physical is %08x\n",(uint32_t)va,*ptet);
			return 0;		   
		    
		}else{
		    page_remove(pgdir,va);
            *ptet=page2pa(pp)|perm|PTE_P;
		    //cprintf("page_insert linear address is %08x, the physical is %08x\n",(uint32_t)va,*ptet);
		    pp->pp_ref++;
			return 0;
		}		
	}else{
	    *ptet=page2pa(pp)|perm|PTE_P;
		 //cprintf("page_insert linear address is %08x, the physical is %08x\n",(uint32_t)va,*ptet);
		 pp->pp_ref++;
	}

	
	//cprintf("page_insert out\n");
	return 0;
}

pgdir_walk() : 用来查找对应线性地址的页表itemboot_map_region() : 进行地址映射,就是把当前的地址空间的分布,映射到新的页目录页表下的地址空间。注意PTE_Wpage_lookup():查找某个线性地址的页表item是否存在,返回对应的物理地址的pageinfo信息. 当需要pageinfo信息时,才调用这个函数 page_remove():  page_insert(): 将某个物理页映射到某个线性地址。

Part3 

Exercise5: 

boot_map_region(kern_pgdir,UPAGES,ROUNDUP(npages*sizeof(struct PageInfo),PGSIZE),PADDR(pages), PTE_U | PTE_P);
 boot_map_region(kern_pgdir,KSTACKTOP-KSTKSIZE,KSTKSIZE,PADDR(bootstack),PTE_W|PTE_P);
 boot_map_region(kern_pgdir,KERNBASE,1<<28,0,PTE_W|PTE_P);
注意:PTE_W,否则即使check_kern_pgdir()通过,页目录切换lrc3时也会出错!!!!
我根据赵炯的书上,这本书上说,当特权用户时,PTE_W不起作用,但是仿佛不是如此!
后来又查了查intel user mannual, 发现赵炯说的是对的,那为什么这里必须要设置PTE_W, 不清楚!!!

Question 2:
Question 3:使用PTE_U这个page drectory/page table选项。
Question 4:因为一开始内存只映射了4M, kernel用去一部分,剩下的全部用于管理内存的话,假设有A byte, 则可以管理的内存为(A/sizeof(struct Pageinfo))*4K
Question 5: 没明白overhead是啥意思!
Question 6: mov $relocated, %eax
                  jmp *%eax 这里的跳转指令跳转到0xfxxxxxxx的线性地址。因为这时的页机制,将线性地址0xf0000000+4M和0x00000000+4M都映射到了物理地址的0-4M之间。
Challenge 1: 4M也模式,映射变化了,需要重新编写我们的映射函数。
Challenge 2: 这个比较简单,调用我们编写的那几个函数就可以实现了。
Challenge 3:这个超级麻烦!如果user process单独使用4G线性地址空间,kernel如何访问user process地址空间呢? 就不能访问了吧? 只能在user proces和kernel process之间                    传递数据了吧??
Callenge 4:linux kernel使用buddy来实现连续物理地址的大内存的申请!!很复杂,看看kernel的书籍吧!!

其他:1. mem_init中映射pages和栈,啥时候用呢? 现在没用吧!!!

学习心得:原来底层编程这么回事,真的比较复杂。学习这个实验,对于我理解计算机体系结构真的帮助很大,对于编程的理解更加的深入了。
                 这些都可以研究明白,而且许多的牛人在研究这个方面,计算机行业,真的很庞大,许多需要学习呀!!!
2013.7.14-2013.7.21

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值