1.要求:
① 指令序列的设定可以执行拟定,格式如表3;
② 在完成了FIFO换页策略后,可以选做LRU的换页策略,并进行比较;
③ 作业允许的页框数m在不同情况下的缺页中断率;
④ 程序运行时显示地址转变和页面调入调出过程。
2.步骤:
① 设计页表及其数据结构:
页号
标志:是否在主存;
页框号:设定页表在主存的位置;
修改标志:设定页面在主存中是否修改过;
磁盘上位置:设定页面在辅存中的位置;
例如:装入新页置换旧页时,若旧页在执行中没有被修改过,则不必将该页重写磁盘。因此,页表中增加是否修改过的标志,执行“存”指令和“写”指令时将对应的修改标志置成“1”表示修改过,否则为“0”表示未修改过。
②设计一个地址转换程序半模拟硬件的地址转换和缺页中断。
当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可以输出转换后的绝对地址来表示一条指令已执行完成。当访问的页不在主存中时,则输出“*页号”来表示硬件产生了一次缺页中断。
#pragma once
#include<stdio.h>
typedef struct page
{
unsigned int pageid;
unsigned int storage;
unsigned int pageframe;
unsigned int flag;
unsigned int address;
}page;
typedef struct operate
{
char operation;
unsigned int pageid;
unsigned int page_address;
}oprate;
//将已经在页表中的页号重新按最久未用排序
void insert(page a[],int i)
{
page temp;
temp = a[i];
for (int p = i; p >0; p--) {
a[p] = a[p-1];
}
a[0] = temp;
}
//将新加入的放在最前面,相当于最久未用
void append(page a[],operate b,page reference[],int number)
{
int n = 0;
page temp;
unsigned int page_frame[4] = {5,8,9,1};
for (int i = 0; i < 7; i++) {
if (b.pageid == reference[i].pageid)
temp = reference[i];
}
n = page_frame[number - 1];
temp.pageframe = n;
if (number == 1)
{
a[0] = temp;
}
if(number > 1)
{
for (int t = number-1; t > 0; t--)
{
a[t] = a[t - 1];
}
a[0] = temp;
}
}
//格式输出
void print_f(page a[], int maxpage,int number)
{
printf("当前页表内的页号为:\n");
for (int m = 0; m < number; m++)
{
printf("pageid:%d storage:%d pageframe:%d flag:%d \n",a[m].pageid,a[m].storage,a[m].pageframe,a[m].flag);
}
printf("\n\n");
}
//置换操作
void page_exchang(page a[],page temp,int maxpage)
{
temp.pageframe = a[maxpage - 1].pageframe;
for (int i = maxpage-1; i > 0 ; i--)
{
a[i] = a[i - 1];
}
a[0] = temp;
}
//页表,新来的操作,页表里的元素个数,最大页表元素个数,参照表
void run_fifo(page a[], operate b, int &number, int maxpage, page reference[])
{
int count_address = 0; //绝对地址
page temp;
int flag_storage = 0; //是否在内存
int flag_cun = 0; //存的标志
char v[] = { 'c','q' };
int j = -1; //中断时取出页号
if (b.operation == v[0]) flag_cun = 1; //如果是存操作
if (number < maxpage) { //如果页表未满,执行以下
printf("没有发生缺页中断\n");
for (int i = 0; i < number; i++)
{
if (b.pageid == a[i].pageid) //页号已经在页表中
{
insert(a,i); //改变页表内顺序
count_address = a[0].pageframe*1024 + b.page_address;
printf("绝对地址%d\n", count_address); //输出绝对地址
flag_storage = 1;
}
} //新加入内存
if (!flag_storage)
{
number += 1; //内存中个数+1
append(a, b, reference, number); //按序排
a[0].storage = 1; //将在内存的标志改为1
if (flag_cun) a[0].flag = 1; //如果操作是”存“,flag =1
count_address = a[0].pageframe*1024 + b.page_address; //计算地址
printf("绝对地址%d\n", count_address); //输出绝对地址
}
}
else //页表已满
{
for (int i = 0; i < number; i++) {
if (b.pageid == a[i].pageid) { //已在内存
printf("没有发生缺页中断\n");
insert(a,i); //改变页表内顺序
count_address = a[0].pageframe * 1024 + b.page_address;
printf("绝对地址%d\n", count_address);
flag_storage = 1;
}
}
if(!flag_storage)
{ //不在页表,发生置换
printf("发生缺页中断\n");
j = a[number - 1].pageid;
printf("\t中断页号: *%d\n", j);
printf("\t输入页:%d\n",b.pageid);
temp = reference[b.pageid]; //改变a中数
if (flag_cun) temp.flag = 1;
if(a[number-1].flag)
printf("第%d页之前为存指令,磁盘位置为:%d\n",a[number-1].pageid,a[number-1].address);
temp.storage = 1;
page_exchang(a,temp,maxpage);
count_address = a[number-1].pageframe*1024 + b.page_address;
printf("\t绝对地址%d\n", count_address);
}
}
}
// ConsoleApplication8.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include"标头.h"
#include <iostream>
#include<string>
using namespace std;
int main()
{
int op_page_number = 0;
int maxpage = 4;
page a[4] = { NULL };
page ref[7] = { {ref[0].pageid = 0 ,ref[0].storage = 0,ref[0].pageframe = NULL,ref[0].flag = 0,ref[0].address = 011},
{ref[1].pageid = 1 ,ref[1].storage = 0,ref[1].pageframe = NULL,ref[1].flag = 0,ref[1].address = 012},
{ref[2].pageid = 2 ,ref[2].storage = 0,ref[2].pageframe = NULL,ref[2].flag = 0,ref[2].address = 013},
{ref[3].pageid = 3 ,ref[3].storage = 0,ref[3].pageframe = NULL,ref[3].flag = 0,ref[3].address = 021},
{ref[4].pageid = 4 ,ref[4].storage = 0,ref[4].pageframe = NULL,ref[4].flag = 0,ref[4].address = 022},
{ref[5].pageid = 5 ,ref[5].storage = 0,ref[5].pageframe = NULL,ref[5].flag = 0,ref[5].address = 023},
{ref[6].pageid = 6 ,ref[6].storage = 0,ref[6].pageframe = NULL,ref[6].flag = 0,ref[6].address = 121} };
operate op_page[12] = { {'+',0,070},{'-',1,050},{'*',2,015},{'c',3,021},
{'q',0,056},{'-',6,040},{'y',4,053},{'+',5,023},
{'c',1,037},{'q',2,78},{'+',4,001},{'c',6,84} };
operate b;
while (true)
{
static int number = 0;
printf("请输入调入第几个操作:\n");
scanf_s("%d", &op_page_number);
if (op_page_number == 99) break;
if (op_page_number < 12)
{
b = op_page[op_page_number];
printf("执行操作:“%c”,页号为:%d ,页内地址为:%d\n",b.operation,b.pageid,b.page_address);
}
else
{
printf("请输入0—11的数\n\n");
continue;
}
run_fifo(a,b,number,maxpage,ref);
print_f(a,maxpage,number);
}
return 0;
}