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

📄 mmu.c

📁 是关于页面替换算法的代码模拟
💻 C
字号:
/*
 * mmu.c	
 * Copyright (c) Inst. of Machine Intelligence at Nankai University
 */
#include "types.h"
#include "mmu.h"
#include "page.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

extern phyaddr_t	cpu_cr3;	
extern phyaddr_t	cpu_cr2;
extern phyaddr_t	cpu_cr0;
extern uint32		cpu_errcode;
extern char memory[];

void handler()
{
	struct Page* new_page;
	new_page=page_alloc();   //分配一个空闲页给临时变量
	page_insert(cpu_cr2,new_page);  //将虚拟地址映射到新分配的页中
}
char	memory[MEMSIZE] = {0};
void (*pgfault_handler)() = handler;

struct Page* pages;
struct Page* free_list;

int mem_end = 0; // memory 中最后一个被使用的字节

int	write_memory(viraddr_t va, char* buf, int size)
{

	int i = 0;
	pde_t* pgdir;
	pte_t* pgtable = 0;
	pde_t	pde = 0;
	pte_t	pte = 0;
//	int start = 0;

	if (!buf){
		printf("\nError: Buffer is NULL.\n");
		exit(1);
	}
	
	if ((cpu_cr0 & PAGING) != PAGING)
	{
		//如果未分页,即物理页和逻辑页一一对应
		for (i = 0; i < size; i++)
			memory[va + i] = buf[i]; //取buf的前size个字节的数据分别存入以va为起点的内存地址

		return 0;
	} 
	else
	{
		pgdir = (pde_t*)(memory + cpu_cr3);//cpu_cr3代表进程要访问页的顶级页表的首位置
	
		for (i = 0; i < size; i++)
		{		
			pde = pgdir[PDX(va + i)];  //pgdir代表顶级页表,PDX(va + i)取虚拟地址的前十位(标识了
			                            //其顶级页表的位置)作为顶级页表的下标,则可以找到顶级页表第
			                          //PDX(va + i)个页表项,每个页表项指向1024个二级页表项
			if ((pde & PTE_P) != PTE_P || (pde & PTE_W) != PTE_W)
			{  //如果顶级页表指向的页表项不在内存中,则产生缺页中断,重新调页
				if (pgfault_handler) //(*pgfault_handler)()可以指向一个中断响应函数
				{
					cpu_cr2 = va + i;
					cpu_errcode = 0x02;
					(*pgfault_handler)();
					i--;
					continue;
				}
				printf("Error: Page Directory is invalid.\n");//如果缺页中断找不到需要的页,则输出
				                                              //提示该页无效
				exit(1);
			}
			
			pgtable = (pde_t*)(memory + PTE_ADDR(pde));//找到二级页表的首地址:取pde表项的前20位,
			                                           //pde的后12位是各种状态标志位
			pte = pgtable[PTX(va + i)];
			if ((pte & PTE_P) != PTE_P || (pde & PTE_W) != PTE_W)
			{
				if (pgfault_handler)
				{
					cpu_cr2 = va + i;
					cpu_errcode = 0x02;
					(*pgfault_handler)();
					i--;
					continue;
				}
				printf("Error: Page Table is invalid.\n");
				exit(1);
			}
			
			memory[PTE_ADDR(pte) + PGOFF(va + i)] = buf[i];  //二级页表表项指向的内存页框号
			                                                 //+ 虚拟地址的后12位页内偏移量
		}
		return 0;
	}
}


int read_memory(viraddr_t va, char* buf, int size)
{

	int i = 0;
	pde_t* pgdir;
	pte_t* pgtable = 0;
	pde_t	pde = 0;
	pte_t	pte = 0;
//	int start = 0;

	
	if (!buf){
		printf("\nError: Buffer is NULL.\n");
		exit(1);
	}
	
	if ((cpu_cr0 & PAGING) != PAGING)
	{
		//未分页
		for (i = 0; i < size; i++)
			buf[i] = memory[va + i];//如果未分页,则物理页和逻辑页一一对应,va为
		return 0;
	} 
	else
	{
		pgdir = (pde_t*)(memory + cpu_cr3);
	
		for (i = 0; i < size; i++)
		{		
			pde = pgdir[PDX(va + i)];
			if ((pde & PTE_P) != PTE_P)
			{
				if (pgfault_handler)
				{
					cpu_cr2 = va + i;
					cpu_errcode = 0x00;
					(*pgfault_handler)();
					i--;
					continue;
				}
				printf("Error: Page Directory is invalid.\n");
				exit(1);
			}
			
			pgtable = (pde_t*)(memory + PTE_ADDR(pde));
			pte = pgtable[PTX(va + i)];
			if ((pte & PTE_P) != PTE_P)
			{
				if (pgfault_handler)
				{
					cpu_cr2 = va + i;
					cpu_errcode = 0x00;
					(*pgfault_handler)();
					i--;
					continue;
				}
				printf("Error: Page Table is invalid.\n");
				exit(1);
			}
			
			buf[i] = memory[PTE_ADDR(pte) + PGOFF(va + i)];
		}
		return 0;
	}
}

⌨️ 快捷键说明

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