⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 page.c

📁 是关于页面替换算法的代码模拟
💻 C
字号:
/*
 * page.c	
 * Copyright (c) Inst. of Machine Intelligence at Nankai University
 */

#include "page.h"
#include <stdlib.h>

struct Page pages[PAGE_NUM];	//实际上,这个数组是在内核空间,也是要占用物理页的,为简单起见,就不要求写在memory里了
struct page_list free_page_list;
extern int mem_end;
extern char memory[];
extern phyaddr_t	cpu_cr3;	
extern phyaddr_t	cpu_cr2;
extern phyaddr_t	cpu_cr0;
extern phyaddr_t	cpu_errcode;

int page_init()
{
	// 初始化空闲页列表
	// 比如,让最后一个物理页最先被分配
	// memory中有哪些物理页可以被使用?哪些不能?
	int i;
	free_page_list.head=NULL;
	for(i=0;i<PAGE_NUM;i++)
	{        
		pages[i].ref = 0;     //先将所有的页的引用置为0;
		if(i*PGSIZE<mem_end)  //如果所引用的页在memory数组中未被使用的第一个字节的位置之前 
			pages[i].ref = 1; //由于存储了页表,故将页的引用为1;
		else
		{
			pages[i].next=free_page_list.head;  //通过next指针连接各个页
			free_page_list.head=&pages[i];     //空闲队列的队头指向最后一页
		}
	}
	return 0;
}

struct Page* page_alloc()
{
	//从空闲页列表中分配一个页, 并返回页面指针

	struct Page* temp=free_page_list.head;
	if(temp==NULL)    //如果没有空闲页了,则退出程序
	{
		printf("There are no more pages free!\n");
		exit(1);
	}			
	else
        free_page_list.head=(free_page_list.head)->next;   //空闲队列的头指针指向下一个page
	return temp;
}

int page_insert(viraddr_t va, struct Page* pp)
{
	//将虚拟地址映射到物理页pp上
	
	pde_t* pgdir;
	pte_t* pgtable = 0;
	pde_t	pde = 0;
	pte_t	pte = 0;
	struct Page * get_pgt;	
	if ((cpu_cr0 & PAGING) != PAGING)         //在main函数中寄存器cpu_cr0=PAGING;已经开启了分页
	{
		//如果未分页的话,退出程序
		printf("Error : Paging mode doesn't exist\n");	
		exit(0);
	} 
	else
	{
		pgdir = (pde_t*)(memory + cpu_cr3);   //pgdir指针指向顶级页表的初始位置
		pde = pgdir[PDX(va)];                 //取出顶级页表的第PDX(va)项		
		if ((pde & PTE_P) != PTE_P)           //如果顶级页表指向的二级页表不存在则需要重新给其分配
		{		
			get_pgt=page_alloc();             //把即将插入的页的下一个空闲页取出用以存二级页表
			pgdir[PDX(va)] = page2pa(get_pgt) | PTE_P ; //最低位或上1,表示新插入的页“在”内存中,同时把新取出的二级页表的地址写入顶级页表
			if (cpu_errcode==0x02)            //若为只读页时cpu_errcode为0,写时cpu_errcode为2
				pgdir[PDX(va)] = pgdir[PDX(va)] | PTE_W ; //此时该顶级页表项后12位等于3,即可写且存在
			get_pgt->ref ++;                  //该页被引用		
			pde = pgdir[PDX(va)];             //取出重置后的新顶级页表项
		}	
		pgtable = (pde_t*)(memory + PTE_ADDR(pde));
		pte = pgtable[PTX(va)];
		if ((pte & PTE_P) != PTE_P)
		{
			pgtable[PTX(va)] = page2pa(pp) | PTE_P ;//最低位或上1,表示新插入的页“在”内存中
			if (cpu_errcode==0x02)			        //若要求可写
				pgtable[PTX(va)]=pgtable[PTX(va)] | PTE_W ;	 //末两位为 11		
			pp->ref ++;
			return 0;                          //完成虚拟地址映射到物理页,函数返回,不执行下面的操作
		}	
		if( page2pa(pp) != PTE_ADDR(pte) )     
		{
			page_remove(va);
			pgtable[PTX(va)] = page2pa(pp) | PTE_P ;
		    pp->ref ++;
		}
		return 0;
	}
}

int page_remove(viraddr_t va)
{
	//移除虚拟页
	//注意,什么时候只是取消映射,什么时候要把页重新放回到空闲页列表中?

	pde_t* pgdir;
	pte_t* pgtable = 0;
	pde_t	pde = 0;
	pte_t	pte = 0;
	struct Page* page_temp=NULL;
	if ((cpu_cr0 & PAGING) != PAGING)
	{
		//如果未分页,则直接退出
		printf("Error : Paging mode doesn't exist\n");	
		exit(0);
	}
	else
	{
		pgdir = (pde_t*)(memory + cpu_cr3);	
		pde = pgdir[PDX(va)];               //取出虚拟地址va对应顶级页表的页表项内容
		if ((pde & PTE_P) != PTE_P)         //若该页本身就不存在,即没有虚拟地址映射,则无法执行移除操作,直接提示后退出
		{		
			printf("Error: Page Directory is invalid.\n");
			exit(1);
		}			
		pgtable = (pde_t*)(memory + PTE_ADDR(pde));  
		pte = pgtable[PTX(va)];	            //取出虚拟地址va对应二级页表的页表项内容
		page_temp=pa2page(PTE_ADDR(pte));	//确定该虚拟地址对应的是哪一页,用page_temp指向它	
		page_temp->ref--;                   //取消该页的引用,使其重新变为自由页
		if((page_temp->ref)==0)
		{
			page_temp->next=free_page_list.head;
			free_page_list.head=page_temp;	//将释放的页插入到空闲队列的队头
		}
	}
	return 0;
}

phyaddr_t page2pa(struct Page* pp)
{
	uint32 idx = pp - pages;               //idx标识pp为内存中的第几页
	phyaddr_t rtv;                         
	rtv = idx * PGSIZE;                    //获得pp页在内存中的位移
	return rtv;
}

struct Page* pa2page(phyaddr_t pa)
{
	struct Page* pp = NULL;                
	pa = ROUNDDOWN(pa, PGSIZE);            //化零取整,使得pa是页大小(4096 B)的整数倍	
	return (pages + (pa / PGSIZE));        //返回pa地址对应的页号
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -