一、实验题目: 模拟请求分页管理中地址转换和缺页中断处理
二、实验目的: 了解内存请求分页管理中地址转换过程与先进先出置换算法和缺页中断处理过程。
三、实验环境:
1、硬件:PC机及其兼容机。
2、软件:Windows OS,MS—DOS OS,Turbo C 或 C++、VC++等。
四、实验内容:
1、 在页式管理中,地址转换是由硬件完成的,实验中设计程序模拟地址转换过程。
5、设计缺页中断处理程序。当对读入的逻辑地址,划分为页号、页内地址后,通过页表发现访问的页不在内存,转入“缺页中断处理”程序去处理。
五、运行示例:
六、算法流程图:
七、程序清单:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<windows.h>
#define PN 7//页面数
#define PAGESIZE 1024//页面大小
typedef struct pagetab{
int no;//页号
int status;//状态 1-该页在内存,0-该页不在内存
int pbo;//物理块号
}PAGETAB;
void menu(PAGETAB pg[]){
int i;
printf("------OS实验四:模拟请求分页管理中地址转换和缺页中断处理------\n");
printf("---输入装入内存的页面号及存入的物理块号(假定分配3个物理块)----\n");
for(i=0;i<3;i++){//初始化页表(一)
scanf("%d",&pg[i].no);
pg[i].status=1;
scanf("%d",&pg[i].pbo);
}
for(i=3;i<PN;i++){//初始化页表(二)
pg[i].no=i;
pg[i].status=0;
}
printf("---------------------------系统菜单---------------------------\n");
printf("--------------------------1.地址转换--------------------------\n");
printf("--------------------------2.显示页表--------------------------\n");
printf("--------------------------0.退出------------------------------\n");
printf("---------------------请输入您需要的功能(0-3)------------------\n");
printf("--------------------------------------------------------------\n");
printf("假设一个物理块的大小为1K。\n使用算法:先进先出页面置换算法。\n");
}
void change(PAGETAB pg[]){//地址转换
int flag=1;
int i;
char queye;
int s=1012,who;//s用于标记先进先出算法所需换出页面的页号(前面加个1),who代表换出的页面号
//(作巧妙处理:s中存一个四位数,百位代表最先进入的页号,个位代表最迟进入的页号)
//(然后who=(s/100)%10,s=(100+s%100)*10+p )
//妙!
int pa,la,p,x;//物理地址,逻辑地址,页号,页内位移
printf("-------地址转换-------\n");
while(flag){
printf("请输入一个逻辑地址LA:");
scanf("%d",&la);
getchar();
p=la/PAGESIZE;
x=la%PAGESIZE;
if(p>=PN)
printf("非法逻辑地址!\n");
else{
for(i=0;i<PN;i++)
if(pg[i].no==p)
if(pg[i].status==0){
printf("1");
queye='Y';
who=(s/100)%10;
printf("%d",who);
s=(100+s%100)+p;
printf("%d",s);
pg[who].status=0;
pg[p].pbo=pg[who].pbo;
pg[p].status=1;
pa=pg[p].pbo*PAGESIZE+x;
printf("逻辑地址:%d\n页号:%d\n页内位移:%d\n是否缺页:%c\n淘汰的页面:%d\n该逻辑地址存储的物理块:%d\n物理地址:%d\n",la,p,x,queye,who,pg[p].pbo,pa);
break;
}
else{
printf("2");
queye='N';
pa=pg[p].pbo*PAGESIZE+x;
printf("逻辑地址:%d\n页号:%d\n页内位移:%d\n是否缺页:%c\n淘汰的页面:\n该逻辑地址存储的物理块:%d\n物理地址:%d\n",la,p,x,queye,pg[p].pbo,pa);
break;
}
}
printf("Do you want to continue?(1-yes 0-no):");
scanf("%d",&flag);
}
}
void show(PAGETAB pg[]){//用于将当前页表中的内容显示出来
int i;
printf("-----------页表显示-----------\n");
printf("页号----状态------物理块号\n");//显示空闲分区表
for(i=0;i<PN;i++)
printf("%d\t%d\t%d\n",pg[i].no,pg[i].status,pg[i].pbo);
printf("显示完毕!\n");
system("pause");
}
void main(){//主函数
int flag=1;
int select;
PAGETAB pg[PN];
while(flag){
menu(pg);
scanf("%d",&select);
switch(select){
case 0:flag=0;break;
case 1:change(pg);break;//地址转换
case 2:show(pg);break;//显示页表
default:printf("输入错误,请重新输入!");break;
}
}
}
八、程序中使用的数据结构及符号说明:
#define PN 7//页面数
#define PAGESIZE 1024//页面大小
typedef struct pagetab{
int no;//页号
int status;//状态 1-该页在内存,0-该页不在内存
int pbo;//物理块号
}PAGETAB;
int s=1012,who;//s用于标记先进先出算法所需换出页面的页号(前面加个1),who代表换出的页面号
int pa,la,p,x;//物理地址,逻辑地址,页号,页内位移
九、调试程序时出现问题说明及解决的方法:
- 如何实现先进先出算法?
解决方法:可以用链表连接的方法,但是我觉得还是复杂了些,就以一种很巧妙的方法去处理了。
int s=1012,who;//s用于标记先进先出算法所需换出页面的页号(前面加个1,因为0不能作为最高位),who代表换出的页面号
//(作巧妙处理:s中存一个四位数,百位代表最先进入的页号,个位代表最迟进入的页号)
//(然后who=(s/100)%10,s=(100+s%100)*10+p )
//太妙了!
- 输入5456D地址时无物理地址数据
解决方法:通过在各语句下面增添printf函数输出一定数据已确定问题出在哪里。最后发现页表的初始化只处理了pg[0]-pg[2],ph[3]-pg[6]没有初始化,也就是说需要分两段将页表初始化好。 - 缺页和没缺页时的输出形式是不一样的
解决方法:在if和else里分别放置不同的输出。
4.将页表初始化放在menu里,让用户知道需要输入什么数据,而非盲目的输入,使程序更具可读性,更易于理解。