📄 main.c
字号:
/*
* main.c
* Copyright (c) Inst. of Machine Intelligence at Nankai University
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mmu.h"
#include "util.h"
#include "page.h"
extern int mem_end;
extern phyaddr_t cpu_cr3;
extern phyaddr_t cpu_cr2;
extern phyaddr_t cpu_cr0;
extern uint32 cpu_errcode;
extern struct page_list free_page_list;
extern char memory[];
int write_file(FILE* file[],struct Page* plist[])
{
int i,j,signal;
signal=0;
for (i=0;i<8;i++)
{
for (j=0;j<5;j++)
{
if (i==(plist[j]->page_number))
{
fprintf(file[i],"%08x ",page2pa(plist[j]));
signal=1;
}
}
if(signal==0)
fprintf(file[i],"%08x ",0);
signal=0;
}
return 0;
}
int main(int argc, char* argv)
{
int read = 0;
int buf = 0;
/*
* 1, 初始化页目录和页表。
* 1) 页目录和页表的内容要写在memory数组里。
* 2) 涉及到memory数组的,都必须用write_memory 和read_memory对其进行读写。以后也是一样
* 3) 全局变量mem_end可以用来指定memory数组中未被使用的第一个字节的位置,
* 4) 将虚拟地址0xf0000000之后的256M空间映射到memory上,可写。
* 5) 将虚拟地址0xe0000000之后的256M空间映射到memory上,只读。
*/
/* Your Code*/
//把顶级页表的1024项(占4×1024Bite)装进内存的前4096项,并对每四个字节
//赋值,计算二级页表的项数:(512M/4k)/1024=128项
int i;
int k;
int j;
int l;
int signal;
int buF1;
int begin;
int begin1;
FILE* vfile[8];
struct Page* new_pagelist[5];
int request[33]={0, 2, 1 ,3, 5 ,4, 6, 3, 7, 3, 3, 0, 1, 2 ,3, 4 ,5 ,0, 1, 2, 3, 4, 5 ,5, 3 ,1, 1 ,1 ,7 ,1 ,3 ,4 ,1 };
char* name[8]={"file0.txt","file1.txt","file2.txt","file3.txt","file4.txt","file5.txt","file6.txt","file7.txt"};
signal=0;
l=0;
begin1=14*64*4; //0xe0000000的前十位为1110 0000 00 即14×64
begin=15*64*4; //0xf0000000的前十位为1111 0000 00 即15×64
buF1=0x00001001; //只读二级页表的初始地址
////////////对虚拟地址0xe0000000映射的顶级页表项的memory数组赋初值
for (i=begin1;i<256+begin1;i=i+4)
{
write_memory(i,(char*)&buF1,4);
buF1+=0x1000;
}
buF1=buF1+2;
////////////对虚拟地址0xf0000000映射的顶级页表项的memory数组赋初值
for (i=begin;i<256+begin;i=i+4)
{
write_memory(i,(char*)&buF1,4);
buF1+=0x1000;
}
/////////////初始化所有的二级页表项,每个二级页表搜索整个4M内存
buF1=0x00000001;
//////////////////////对只读二级页表的初始化
for (k=1;k<65;k++)
{
for (i=k*4*1024;i<(k+1)*1024*4;i=i+4)
{
write_memory(i,(char*)&buF1,4);
buF1+=0x1000;
}
buF1=0x00000001;
}
///////////////////////对可写二级页表的初始化
buF1=0x00000003;
for (k=65;k<129;k++)
{
for (i=k*4*1024;i<(k+1)*1024*4;i=i+4)
{
write_memory(i,(char*)&buF1,4);
buF1+=0x1000;
}
buF1=0x00000003;
}
mem_end=129*PGSIZE;
/*
* 2, 开启CPU的分页模式
*/
/* Your Code*/
cpu_cr0=PAGING;
//如果完成了前2个工作,就把这两句话注释掉。
//printf("Page table isn't ready!\n");
//exit(0);
/*
* 测试前两个步骤
*/
read = 0;
read_memory(0xf0000000 + PDX(0xf0000000) * 4, (char *)&read, 4); //计算后read=0x4003;
//...0xf0000000 + PDX(0xf0000000) * 4...为f0000f00/////
assert(read == ((int*)memory)[PDX(0xf0000000)]);//验证read,恰好相等
buf = 0x00646c72;
write_memory(0xf0100000, (char *)&buf, 4);
read_memory(0xe0100000, (char *)&read, 4);
printf("H%x, Wo%s\n", 57616, &read); //57616的16进制数为e110
check_pgdir();
/*
* 3, 实现页管理
*/
page_init();
//测试
/*
* 4,缺页中断
* 自定义一个中断响应函数,然后将函数地址赋给pgfault_handler.
*/
/* Your Code*/
//测试
buf = 0x12345678;
write_memory(0xd0000000, (char*)&buf, 4);
read_memory(0xd0000000, (char*)&read, 4);
assert(read == buf);
/*
* 5, 页替换
* 1), 新建一个可替换页列表,从空闲列表中分配5个物理页,放入可替换列表中。
* 2), 在这个替换列表中,实现页替换算法。
* 3), 在测试用例中,有33个请求,对应每个页的前33个4字节。如果页在第i次请求中
* 位于内存中,记录该物理页的首地址。
* 如果没有被加载进内存,将第i个4字节清0。
* 4), 完成测试用例后,将所有页的内容写入磁盘,保存为txt格式,每个虚页有一个
* 文件。在文件中用空格分开每一次请求的值。也就是文件中用空格分开了33项。
* 物理地址用16进制表示(%08x)。
*/
// 测试
// 输入页请求序列:0 2 1 3 5 4 6 3 7 3 3 0 1 2 3 4 5 0 1 2 3 4 5 5 3 1 1 1 7 1 3 4 1
// 以表格的形式输出结果,表格中只记录虚页编号
//////////////////////////////////////////////////////FIFO 先进先出算法
for (i=0;i<5;i++)
{
new_pagelist[i]=page_alloc();
new_pagelist[i]->page_number=-1;
// new_pagelist[i]->hit_num=0;
}
for (i=0;i<8;i++)
{
vfile[i]=fopen(name[i],"w");
}
for (i=0;i<33;i++)
{
k=request[i]<<12;
for (j=0;j<5;j++)
{
if (request[i]==(new_pagelist[j]->page_number))
signal=1;
}
if(signal==0) //signal==0说明没有命中请求的页号
{
page_insert(k,new_pagelist[l]);
(new_pagelist[l])->page_number=request[i];
l=(l+1)%5;
}
write_file(vfile,new_pagelist);
signal=0;
}
for (i=0;i<8;i++)
{
fclose(vfile[i]);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -