📄 os4.cpp
字号:
//os4.cpp--采用FIFO的页式虚拟存储管理的地址转换和缺页中断
#include <iostream.h>
#include <iomanip.h>
#include <ctype.h>
//页表用数组模拟,在实验中页表数据结构定义为:
#define N 32 //实验中假定的页表长度,页表的长度实际上是由系统按照作业长度决定的
#define M 4 //实验中用,用固定局部置换算法给每个进程分配的主存物理块数
struct
{int lnumber; //页号
int flag; //表示该页是否在主存,"1"表示在主存,"0"表示不在主存
int pnumber; //该页所在主存块的块号
int write; //该页是否被修改过,"1"表示修改过,"0"表示没有修改过
int dnumber; //该页存放在磁盘上的位置,即磁盘块号
}page[N]; //页表定义
int p[M]; //用数组模拟]FIFO算法中的队列(使用循环队列)
int head;
void initial(void); //初始化
int do_mmap(int); //模拟地址转换
void do_page_fault(int); //缺页中断处理程序
void run_first_instructon(int); //执行进程的第一条指令
void run_a_instruction(int); //CPU执行一条指令
void print_page_and_fifoqueue(void); //输出页表和FIFO队列
main()
{
int laddress, paddress; //逻辑地址,物理地址
int lnumber, ad, pnumber; //页号,页内地址和物理块号
initial(); //手工初始化页表
print_page_and_fifoqueue(); //输出页表和FIFO队列
run_first_instructon(0x0000); //运行进程的第一条指令的地址
//输入下一条指令的地址
cout<<"输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl;
cin>>laddress;
while(laddress>32767){ //输入正确性检测
cout<<"Enter ERORR! 请重新输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl;
cin>>laddress;
}
while(laddress!=-1){ //还有指令要执行
lnumber=laddress>>10; //取逻辑地址的页号lnumber
if(page[lnumber].flag==1){ //指令所在的页面已装入在内存中
paddress=do_mmap(laddress); //形成物理地址
cout<<paddress<<"输出转换后的物理地址"<<endl;
run_a_instruction(paddress); //CPU根据得到的物理地址去执行指令
cout<<"此指令执行是否修改所在页面lnumber="<<lnumber<<"(y/n?) ";
char change;
cin>>change;
if(tolower(change)=='y'){
page[lnumber].write=1; //若页面要已修改,则将此页面修改位置1
print_page_and_fifoqueue();
}
}
else{ //缺页中断
cout<<lnumber<<"输出该页的页号--表示硬件产生缺页中断"<<endl;
do_page_fault(lnumber); //直接转去缺页中断处理
continue; //本循环结束,重新执行指令
}
cout<<"输入下一条指令的逻辑地址((0~32767)),-1 to end.\n";
cin>>laddress;
while(laddress>32767){ //输入正确性检测
cout<<"Enter ERORR! 请重新输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl;
cin>>laddress;
}
}
cout<<"祝贺,进程运行结束!"<<endl;
system("PAUSE");
return 0;
}
//手工初始化页表和p[M]队列
void initial(void)
{
int i;
for(i=0; i<=31; i++){
page[i].lnumber=i;
if(i<=M-1){ //预装入算法初始化页表的前四项
cout<<"输入页号为 "<<i<<" 所在内存的物理块号(预装入前四个页面):";
cin>>page[i].pnumber;
page[i].flag=1; //存在标志置1
}
}
//初始化FIFO的队列
head=0;
for(i=0; i<=M-1; i++)
p[i]=i;
}
//输出页表和FIFO队列
void print_page_and_fifoqueue(void)
{
int i;
cout<<"Print the page table.\n";
cout<<setw(10)<<"lnumber"<<setw(9)<<"flag"<<setw(10)<<"pnumber"
<<setw(10)<<"write"<<setw(10)<<"dnumber"<<endl;
for(i=0; i<=N-1; i++)
cout<<setw(7)<<page[i].lnumber<<setw(10)<<page[i].flag<<setw(10)<<page[i].pnumber
<<setw(10)<<page[i].write<<setw(10)<<page[i].dnumber<<endl;
cout<<"Print the FIFO queue.\n";
cout<<setw(10)<<"NO"<<setw(40)<<"page(已在主存的页号lnumber)\n";
cout<<"head="<<head<<endl;
for(i=0; i<=M-1;i++)
cout<<setw(10)<<i<<setw(15)<<p[i]<<endl;
}
//模拟地址转换
int do_mmap(int laddress)
{
int lnumber, ad, pnumber, paddress;
lnumber=laddress>>10; //取逻辑地址的页号lnumber
ad=laddress&0x3ff; //页内地址
pnumber=page[lnumber].pnumber; //从页表中取得块号pnumber
paddress=pnumber<<10|ad;
return paddress;
}
//CPU执行一条指令,输出物理地址表示指令执行完成
void run_a_instruction(int paddress)
{
cout<<paddress<<" 输出物理地址--表示指令执行完成"<<endl;
}
//执行进程的第一条指令
void run_first_instructon(int laddress)
{
int lnumber, ad, pnumber, paddress;
lnumber=laddress>>10; //取逻辑地址的页号
if(page[lnumber].flag==1) //由于式预装入方式,所以第一条指令所在的页面肯定在内存中
paddress=do_mmap(laddress); //形成物理地址
cout<<paddress<<"输出转换后的物理地址"<<endl;
run_a_instruction(paddress);
cout<<"此指令执行(0x0000)是否修改所在页面lnumber="<<lnumber<<"(y/n?) ";
char change;
cin>>change;
if(tolower(change)=='y'){ //若指令执行完时修改了页面,则置write标志位位1
page[lnumber].write=1;
print_page_and_fifoqueue();
}
cout<<"********第一条指令执行完成(地址为0x0000)***********"<<endl;
}
//页面写回磁盘
void write_to_harddisk(int j)
{
cout<<j<<"输出已修改的淘汰的页号--表示该页写回了磁盘"<<endl;
}
//缺页中断处理程序
void do_page_fault(int lnumber)
{
int j; //j是选择淘汰的页
j=p[head];
p[head]=lnumber; //lnumber是新装入的页号
head=(head+1)%M;
//若淘汰出主存的页j已修改,则写会磁盘
if(page[j].write==1)
write_to_harddisk(j); //页j写回磁盘
//修改页表
page[j].flag=0; //页表中第j页的存在标志为0
page[lnumber].flag=1; //页表第lnumber的存在标志为1
page[lnumber].write=0; //页表第lnumber的修改标志为0
page[lnumber].pnumber=page[j].pnumber; //第拉怒目布尔页的主存块号为第j页原主存块号
cout<<lnumber<<"输出该页--表示该页调入了主存"<<endl;
cout<<"按任意键将查看“页面置换”之后的页表page[N]和FIFO队列信息"<<endl;
system("PAUSE");
print_page_and_fifoqueue();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -