资源描述
实验题目:页式虚拟存储器管理中地址转换和缺页中断
一、 实验目的
1、 深入了解页式存储管理如何实现地址转换;
2、 进一步认识页式虚拟存储管理中如何实现缺页中断。
二、 实验预备知识
1、 页式存储管理中地址转换的方法;
2、 页式虚拟存储的缺页中断处理方法。
三、 实验内容
编写程序完成页式虚拟存储管理中地址转换过程和模拟缺页中断的处理。实验具体包括:首先对给定的地址进行地址转换工作,若发生缺页则先进行缺页中断处理,然后再进行地址转换;最后编写主函数对所做工作进行测试。
假定内存64KB,每个内存块1K(1024字节),作业最大支持到64KB,系统中每个作业分得内存块4块。
[提示]
1、页式存储管理中地址转换过程:假设内存块的大小为2n字节,内存大小为2m字节和逻辑地址m位,则进行地址转换时,首先从逻辑地址中的高m-n位中取得页号,然后根据页号查页表,得到块号,并将块号放入物理地址的高m-n位,最后从逻辑地址中取得低n位放入物理地址的低n位就得到了物理地址,实验中使用软件模拟地址的转换过程,模拟地址转换的流程如下:
2、缺页处理过程
(1)根据当前执行指令中逻辑地址的页号查页表,判断该页是否在主存储器中,若该页标志为“0”,形成缺页中断。中断装置通过交换PSW让操作系统的中断处理程序占用处理机;
(2)操作系统处理缺页中断的方法就是查内存分配表,找一个空闲内存块;若无空闲块,查找表,选择一个已在内存的页面,把它暂时调出内存。若在执行过程中该页被修改过,则需将该页信息写回磁盘,否则不必写回;
(3)找出该页的磁盘位置,启动磁盘读出该页信息,把磁盘上读出的信息装入到第2步找到内存块,修改页表中该页的标志为“1”;
(4)由于产生缺页中断的那条指令没有执行完,所以页面装入后应重新执行被中断的指令。当重新执行该指令时,由于要访问的页面已在内存中,所以可正常执行。
程序代码
ia #include
#define n 64 //页表的最大长度
#define length 4 //系统为每个作业分配的主存块数
struct{
int lnumber; //页号
int flag; //表示页是否在主存中,“1”表示在,“0”表示不在
int pnumber; //该页所在主存块的块号
int write; //该页是否被修改过,“1”表示修改过,“0“表示没有修改过
int dnumber; //该页存放在磁盘上的位置,即磁盘块号
}page[n]; //页表定义
int m;
int page_length; //页表的实际长度
int p[length]; //用向量模拟主存
int head;
void page_interrupt(int); //缺页中断处理函数
void command(unsigned, int); //命令处理函数
void main(){
int lnumber,pnumber,write,dnumber;
unsigned laddress;
int i;
cout<<"输入页表的信息,创建页表(页号从0开始,若页号为-1,则结束输入) ";
cout<<"请输入页号和辅存地址:";
cin>>lnumber>>dnumber;
cin.ignore ();
i=0;
while(lnumber!=-1){
page[i].lnumber=lnumber;
page[i].flag=0;
page[i].write=0;
page[i].dnumber=dnumber;
i++;
cout<<"请输入页号和辅存地址:";
cin>>lnumber>>dnumber;
}
//预先将输入的页调入主存块中
page_length=i;
cout<<"输入主存块号(输入少于或者等于"<<i<<"个数据,若块号数为-1,则结束输入):";
cin>>pnumber;
cin.ignore ();
m=0;
head=0;
while(m<LENGTH&&PNUMBER!=-1){
if(m<I){
page[m].pnumber=pnumber;
page[m].flag=1;//调入主存后,标志为置1
p[m]=m; //记录主存中的页号
m++;
}
cout<<"输入主存块号(输入少于或者等于"<<i<<"个数据,若块号数为-1,则结束输入):";
cin>>pnumber;
cin.ignore ();
}//while
cout<<"输入指令性质(1-修改,0-不需要,其他-结束程序运行)和逻辑地址 "
<<"逻辑地址最大能支持2的16次方-1=65535。";
cout<<"输入指令性质:";
cin>>write;
cin.ignore ();
cout<<"输入逻辑地址:";
cin>>laddress;
cin.ignore ();
while(write=0||write=1){
command(laddress,write); //将输入的逻辑地址转换成物理地址
cout<<"输入指令性质:";
cin.ignore ();
if(write!=0&&write!=1) break;
cout<<"输入逻辑地址:";
cin>>laddress;
cin.ignore ();
}//while
}//main
//中断处理函数,采用先进现出的页面调度算法//
void page_interrupt(int lnumber){
int j;
cout<<"发生缺页中断"<<LNUMBER<<ENDL;
j=p[head];
p[head]=lnumber;
head=(head+1)%m;
if(page[j].write==1)
cout<<"将页 "<<J<<" 写回磁盘第 ?<<page[j].dnumber<
page[j].flag=0;
page[lnumber].pnumber=page[j].pnumber;
page[lnumber].flag=1;
page[lnumber].write=0;
cout<<"淘汰主存块 "<<PAGE[J].PNUMBER<<" 中的页 ?<<j<
<<PAGE[LNUMBER].DNUMBER<<" 块中调入页 ?<<lnumber<<endl;
}
//地址转换函数,将逻辑地址转换成物理地址,如果要查找的页不在主存当中则产生缺页中断//
void command(unsigned laddress,int write){
unsigned paddress,ad,pnumber;
int lnumber;
kk:
lnumber=laddress>>10; //取逻辑地址高6位,页号
ad=laddress&0x3ff; //页内地址
cout<<"该逻辑地址的页号为:"<<LNUMBER<<" 页内地址为:?<<ad<<endl;
if(lnumber>=page_length){ //页号大于页表的长度,则无效页号
cout<<"该页不存在!";
return;
}
if(page[lnumber].flag==1){ //页号为lnumber 在内存当中
pnumber=page[lnumber].pnumber;
paddress=pnumber<<10|ad;
cout<<"逻辑地址是:"<<LADDRESS<<" 对应物理地址是:?<<paddress<<endl;
if(write==1) //该页被修改过
page[lnumber].write=1;
}
else{ //页号为lnumber不在内存当中,则产生缺页中断
page_interrupt(lnumber);
goto kk;
}
}//command
</i<<"个数据,若块号数为-1,则结束输入):";
</i<<"个数据,若块号数为-1,则结束输入):";
5 / 5
展开阅读全文