您的位置:首页 > 其它

页面调度-FIFO

2015-11-16 21:50 162 查看
1. 原理



图1:请求页式存储管理模拟程序的完整流程图



图2:一条指令执行的模拟流程图



图3:模拟地址转换的流程图



图4:采用FIFO页面置换算法的缺页中断流程图

2.C++ code

// Page_V1.cpp : 定义控制台应用程序的入口点。
/*
*Name:Page_V1.cpp
*Author:WangLin
*Created On:2015/11/16
*Function:模拟页面调度。地址转换:十进制输入,十进制输出
*/

#include "stdafx.h"
#include<iostream>

using namespace std;
const int  N=64;//页表最大长度
int n;//页表实际长度
int m;//队列长度
int head=0,tail=0,used
,p
;//队列头/尾指针/标记数组,存放页号的优先队列

struct//页表
{
int Number;//页号
int pNumber;//物理块号
int dNumber;//在磁盘上的位置
int write;//修改标志
int flag;//存在标志
}page
;

void printPageTable()//打印页表内容
{
cout<<"当前页表内容为:"
<<endl<<"================================================================================"<<endl;
cout<<"页号       "<<"物理块号    "<<"磁盘位置    "<<"修改标志    "<<"存在标志    "<<endl
<<"================================================================================"<<endl;
for(int i=0;i<n;++i)
{
cout<<page[i].Number<<"     ";
cout<<page[i].pNumber<<"        ";
cout<<page[i].dNumber<<"        ";
cout<<page[i].write<<"      ";
cout<<page[i].flag<<"       "<<endl;
}
}
void printQueue()//打印优先队列内容
{
cout<<"======================="<<endl<<"当前队列为:"<<endl;
cout<<"-队首-"<<endl;

int i=head,j=0;
while(1)
{
if(used[i]==-1)
cout<<"页号"<<p[i]<<endl;
j++;
if(j==m)break;
i=(i+1)%m;
}
cout<<"-队尾-"<<endl;
}

void creatPageTable()//创建页表
{
int i=0;
cout<<"输入页表的信息,创建页表"<<endl<<"请输入页表项数n:";
cin>>n;
while(i<n)
{
cout<<"输入第"<<i<<"页的辅存地址:";
cin>>page[i].dNumber;
page[i].Number=i;
page[i].pNumber=-1;
page[i].write=page[i].flag=0;
i++;
}
cout<<"页表创建完毕!"<<endl;
printPageTable();

//为进程分配主存
cout<<"输入分配给该进程的主存块数(<"<<n<<"):";
cin>>m;
int *p=new int[m];
cout<<"当前页号队列为空!"<<endl;
//return p;
}
void startOperate()//指令执行
{
cout<<endl<<"++++++++++++++++++++++++++++++++++++"<<endl<<"开始指令操作!"<<endl<<endl;
int i,lgcaddr,ad,paddr;//页号,逻辑地址,页内偏移,物理地址
char ch;
//cout<<"输入要调用的页号(<"<<n<<"):";
cout<<"输入逻辑地址:";
cin>>lgcaddr;
cout<<endl<<"是否对页进行修改(y/n):";
cin>>ch;

i=lgcaddr>>10;//页号
ad=lgcaddr&0x3ff;//页内偏移
if(i<n)
{
//第1步,查看页表
if(page[i].flag==1)//在内存中,即在页号队列p[]中,形成物理地址输出
{
cout<<"第"<<i<<"页已在主存中,物理地址是:";
i=page[i].pNumber;//由页号找到物理块号
paddr=i<<10|ad;//合并物理块号和页内偏移,形成物理地址
cout<<paddr<<endl;
}
else//不在内存中,从磁盘中调入到p[]中,插在队尾
{
cout<<"从磁盘"<<page[i].dNumber<<"调入页"<<i<<"..."<<endl;
if(used[tail]!=-1)//如果队列未满
{
p[tail]=i;//插在队列尾部
used[tail]=-1;//标记队列此处已被占用
page[i].pNumber=tail;//物理块为此时队列位置下标
page[i].flag=1;//修改标志为存在
tail=(tail+1)%m;//tail指向下一个位置

//如果要修改页表
if(ch=='y'||ch=='Y')page[i].write=1;
cout<<"页号"<<i<<"    成功调入内存!"<<endl;
}
else//队列已满,选择队首替换出去
{
//淘汰队首页
cout<<"队列已满!淘汰队首页,页号为"<<p[head]<<endl;
page[p[head]].flag=page[p[head]].pNumber=0;
if(page[p[head]].write==1){cout<<"页号"<<p[head]<<"   内容写入到辅存!";}//换出之前写入到辅存中
page[p[head]].write=0;
cout<<endl<<"页号"<<p[head]<<"    淘汰成功!"<<endl;

page[i].flag=1;
page[i].pNumber=head;
page[i].write=0;
p[head]=i;
head=(head+1)%m;
cout<<"页号"<<i<<"    成功调入内存!"<<endl;
}
//形成物理地址输出
cout<<"第"<<i<<"页的物理地址是:";
i=page[i].pNumber;//由页号找到物理块号
paddr=i<<10|ad;//合并物理块号和页内偏移,形成物理地址
cout<<paddr<<endl;
}
cout<<endl<<"是否打印页表和队列(y/n):";
cin>>ch;
if(ch=='y'||ch=='Y')
{
printPageTable();
printQueue();
}
}
else
cout<<"输入的页号大于页表长度,越界!页面调度失败:"<<endl;
cout<<"指令执行完毕!"<<endl<<"++++++++++++++++++++++++++++++++++++"<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
creatPageTable();//p是页号队列
char ch='y';
while(ch=='y'||ch=='Y')
{
startOperate();
cout<<"继续执行指令(y/n):";
cin>>ch;
}

return 0;
}


3. 运行结果















4 .总结

本实验中,对队列的处理有些粗糙,仅仅能保证正确,质量不高,用used[]标记数组个人感觉也是很笨拙的办法。另外,代码多处都可以进一步优化,总之还有许多不足的地方,有空再继续回来修改。

小技巧:直接在dos下用python的bin(a)函数和int(”,2)函数可以检测十进制和而二进制的转换。

python相当于简易计算器啊~~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息