院系:计算机学院
实验课程:操作系统实验
实验项目:模拟操作系统的页面置换
指导老师:李晶晶
开课时间:2017-2018年第2学期
专业:网络工程
班级:网工7班
姓名:LRE
学号:20162180014
⼀、实验名称
模拟操作系统的页⾯置换
⼆、实验⽬的
1、掌握操作系统的页⾯置换过程,加深理解页式虚拟存储 器的实现原理。
2、掌握⽤随机数⽣成满⾜⼀定条件的指令地址流的⽅法。
3、掌握页⾯置换的模拟⽅法。
三、实验要求,主要内容
1、采⽤⼀种熟悉的语⾔,如 C、PASCAL 或 C++等,编 制程序,最好关键代码采⽤ C/C++,界⾯设计可采⽤其它⾃⼰ 喜欢的语⾔
2、模拟操作系统采⽤ OPT、FIFO 和 LRU 算法进⾏页 ⾯置换的过程。
3、设程序中地址范围为0到32767,采⽤随机数⽣成256 个 指令地址,满⾜50%的地址是顺序执⾏,25%向前跳,25%向 后跳。 为满⾜上述条件,可采取下列⽅法:设d0=10000,第n个指 令地址为dn,第n+1个指令地址为dn+1,n的取值范围为0到 255。 每次⽣成⼀个1到1024范围内的随机数a,如果a落在1到 512范 围内,则dn+1=dn+1。如果a落在513到768范围内,则设置dn+1为 1到dn范围内⼀个随机数。如果a落在769到1024范围内,则设置 dn+1为dn到32767范围内⼀个随机数。 例如:srand();初始化⼀ 个随机函数。
a[0]=10*rand()/32767*255+1;a[1]=10*rand()/32767*a[0]...语 句 可⽤来产⽣a[0]与a[1]中的随机数。
或采⽤以下⽅式:
(1)通过随机数产⽣⼀个指令序列,共320条指令。指令的地址按 下述原则⽣成: A:50%的指令是顺序执⾏的
B:25%的指令是均匀分布在前地址部分
C:25%的指令是均匀分布在后地址部分
具体的实施⽅法是:
A:在[0,319]的指令地址之间随机选取⼀起点m
B:顺序执⾏⼀条指令,即执⾏地址为m+1的指令
C:在前地址[0,m+1]中随机选取⼀条指令并执⾏,该指令的地 址为m'
D:顺序执⾏⼀条指令,其地址为m'+1
E:在后地址[m'+2,319]中随机选取⼀条指令并执⾏
F:重复步骤A-E,直到320次指令
(2)将指令序列变换为页地址流
设:页⾯⼤⼩为1K; ⽤户内存容量4页到32页; ⽤户虚存容量为32K。 在⽤户虚存中,按每K存放10条指令排列虚存地址,即320条指 令在虚存中的存放⽅式为:
第0条-第9条指令为第0页(对应虚存地址为[0,9])
第10条-第19条指令为第1页(对应虚存地址为[10,19])
....................................
第310条-第319条指令为第31页(对应虚存地址为[310,319])
按以上⽅式,⽤户指令可组成32页。
4、页⾯⼤⼩的取值范围为1K,2K,4K,8K,16K。按照 页⾯⼤⼩将指令地址转化为页号。对于相邻相同的页号,合并 为⼀个。
5、分配给程序的内存块数取值范围为1块,2 块,直到程 序的页⾯数。
6、分别采⽤OPT、FIFO 和LRU算法对页号序列进⾏调度, 计算出对应的缺页中断率。
7、打印出页⾯⼤⼩、分配给程序的内存块数、算法名、对 应的缺页中断率 。
8、分析页⾯⼤⼩和分配给程序的内存块数对缺页中断率的 影响。分析不同的页⾯置换算法的调度性能。
四.程序的主要流程图:
主程序流程:
OPT算法流程:
FIFO算法流程图:
LRU算法流程图:
五.程序主要功能函数:
主函数:
OPT算法:
FIFO算法:
LRU算法:
部分程序运行截图:
六.实验数据分析:
现选取部分程序数据分析如下:
当页面大小为2K时,OPT,FIFO,LRU对应的缺页中断率随分配的物理块数的变化情况如下:
当页面大小为4K时,OPT,FIFO,LRU对应的缺页中断率随分配的物理块数的变化情况如下:
由此,容易看出,无论是哪一种页面置换算法,随着分配给的物理块数的增加,缺页中断率都在下降。而总体来看,OPT算法比LRU和FIFO更胜一筹,LRU次之,但也能做到和OPT十分接近的水准,FIFO的缺页中断率较高,是一种效率很低的做法。
七.实验心得:
通过本次实验,手工进行了操作系统中OPT,FIFO,LRU三种页面置换算法的模拟,加深了对操作系统页面置换算法的理解,收获良多。同时,在编程的过程中,也提升了编写代码的能力。
源程序清单:
#include<iostream>
#include<string.h>
#include<time.h>
#include<queue>
#include<set>
#include<stdio.h>
#include<string.h>
using namespace std;
int d[321];//d[i]表示以i为起点取出下一条指令的地址的位置
int size;//页面大小
int num;//物理块块数
int my_rand(int a,int b)//生成从a到b的随机数
{
return rand()%(b-a+1)+a;
}
//将指令地址转化为页号
int get_page(int ins,int size)
{
return ins/(size*10);
}
void OPT()
{
int T=320;
int memory[num];
memset(memory,-1,sizeof(memory));
set<int> st;//用一个集合来表示主存中存放的页面
int page;
int cnt=0;
int instruction[321];
int NUM_OF_PAGE;
if(320%(size*10)==0)NUM_OF_PAGE=320/(size*10);
else NUM_OF_PAGE=320/(size*10)+1;
for(int i=1;i<=320;i++)
{
instruction[i]=my_rand(1,320);
}
int times[NUM_OF_PAGE];//当前考虑下剩下指令中各种指令还将出现的次数
int m;
for(int i=1;i<=320;i++)
{
m=instruction[i];
page=get_page(m,size);
if(st.count(page))continue;//若页面已经调入主存
else
{
bool f=0;
for(int k=0;k<num;k++)
{
if(memory[k]==-1)
{
memory[k]=page;
st.insert(page);
f=1;
break;
}
}
if(!f)
{
memset(times,0,sizeof(times));
for(int j=i+1;j<=320;j++)
{
times[get_page(instruction[j],size)]++;
}
//选择主存中剩下指令中将会出现次数最小的那个进行页面置换;
int choice=0;
for(int k=0;k<num;k++)
{
if(times[memory[choice]]>times[memory[k]])choice=k;
}
st.erase(memory[choice]);
memory[choice]=page;
st.insert(page);
}
cnt++;
}
}
cout<<"使用先进先出OPT算法的缺页中断率为:"<<(1.0)*cnt/320<<endl;
}
void FIFO()
{
int m;
int T=320;
queue<int> q;//用一个队列来表示num个物理块构成的主存空间
set<int> st;//用一个集合来表示主存中存放的页面
int page;
int cnt=0;
while(T--)//随机取320条指令组成一个"程序"
{
m=my_rand(1,320);
page=get_page(m,size);//这条指令所在页号为page
if(st.count(page))continue;//若页面已经调入主存
else
{
if(q.size()<num)
{
q.push(page);
st.insert(page);
}
else
{
st.erase(q.front());
q.pop();
q.push(page);
st.insert(page);
}
cnt++;//发生了缺页中断
}
}
cout<<"使用先进先出FIFO算法的缺页中断率为:"<<(1.0)*cnt/320<<endl;
}
void LRU()
{
int T=320;
int memory[num];
memset(memory,-1,sizeof(memory));
set<int> st;//用一个集合来表示主存中存放的页面
int page;
int cnt=0;
int instruction[321];
int NUM_OF_PAGE;
if(320%(size*10)==0)NUM_OF_PAGE=320/(size*10);
else NUM_OF_PAGE=320/(size*10)+1;
for(int i=1;i<=320;i++)
{
instruction[i]=my_rand(1,320);
}
int times[NUM_OF_PAGE];//当前各种页面已经出现过的次数
memset(times,0,sizeof(times));
int m;
for(int i=1;i<=320;i++)
{
m=instruction[i];
page=get_page(m,size);
if(st.count(page))continue;//若页面已经调入主存
else
{
bool f=0;
for(int k=0;k<num;k++)
{
if(memory[k]==-1)
{
memory[k]=page;
st.insert(page);
f=1;
break;
}
}
if(!f)
{
memset(times,0,sizeof(times));
for(int j=i+1;j<=320;j++)
{
times[get_page(instruction[j],size)]++;
}
//选择主存中当前已经出现过的页面出现次数最小的那个进行页面置换;
int choice=0;
for(int k=0;k<num;k++)
{
if(times[memory[choice]]>times[memory[k]])choice=k;
}
st.erase(memory[choice]);
memory[choice]=page;
st.insert(page);
}
cnt++;
}
}
cout<<"使用先进先出LRU算法的缺页中断率为:"<<(1.0)*cnt/320<<endl;
}
int main()
{
int page_size[5]={1,2,4,8,16};
for(int i=0;i<5;i++)
{
size=page_size[i];
int p;
if(320%(size*10)==0)p=320/(size*10);
else p=320/(size*10)+1;
for(int j=1;j<=p;j++)
{
num=j;
cout<<"页面大小:"<<size<<"K 内存物理块数:"<<num<<endl;
OPT();
FIFO();
LRU();
cout<<endl<<endl;
}
}
return 0;
}