页面置换 一.目的和要求
(一)目的
存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常
用的虚拟存储管理技术。
本实验的目的是通过请求页式管理中页面置换算法的模拟设计,来了
解虚拟存储技术的特点,掌握请求页式管理的页面置换算法。
(二)要求
模拟页式虚拟存储管理中硬件的地址转换和缺页中断,并用先进先出
调度算法(FIFO)处理缺页中断。
二.实验内容
(1)为了装入一个页面而必须调出一页时,如果被选中调出的页面在执行中没有修改过,则不必把该页写到磁盘上。因此,在页表中可以增加是否修改过的标志,当执行“存”指令 “写”指令是把对应页的修改标志置“1”表示该页修改过,为“0”表示该页没有修改过。
(2)设计一个地址转换程序来模拟硬件的地址转换和缺页中断。当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可用输出转换后的绝对地址来表示一条指令已完成。当访问的页不在主存时则输出“*该页页号”来表示硬件产生了一次缺页中断。调用模拟地址转换程序。
(3)编制一个FIFO页面调试程序。FIFO页面调试算法总是先调出作业中最先进入主存的那一页,因此,可以用一个数组来构成页号队列。数组中每个元素是该作业已在主存的页面好,假定分配给作业的主存块数为m,且该作业开始的m页已装入主存,则数组可有m个元素组成:P[0],P[1],„,P[m-1] 她们的初值为:P[0]:=0,P[1]:=1,„,P[m-1]:=m-1
用一指针k指示当要装入新页时应调出的页在数组的位置,k的初值为0。当产生缺页中断后,操作系统总是选择P[k]所指出的页面调出,然后执行: P[k]:=要装入的新页页号 K:=(k+1)mod m (4)假定主存的每块长度为1024个字节,现有一个共7页的作业,其副本也已在磁盘上.系统为该作业分配了4块主存块,且该作业的第0页至第3页已经装入主存,其余3页尚未装入主存,该作业的页表如下:
假设该作业依次执行的指令如下:
三.实验流程图
四.实验程序
#include #include #include #include
#define N 6//实验中假定的页表长度 #define M 4 //主存物理块数 struct
{int lnumber; //页号
int flag; //表示该页是否在主存,
int write; //该页是否被修改过,
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
while(laddress>32767){
cout
cin>>laddress; }
while(laddress!=-1){
lnumber=laddress>>10; //取逻辑地址的页号lnumber
if(page[lnumber].flag==1){ //指令所在的页面已装入在内存中 paddress=do_mmap(laddress); //形成物理地址
cout
cout
if(tolower(change)=='y'){ page[lnumber].write=1; print_page_and_fifoqueue(); } }
else{ //缺页中断
cout
do_page_fault(lnumber); //直接转去缺页中断处理
continue; //本循环结束,重新执行指令 }
cout
while(laddress>32767){ //输入正确性检测
cout
cout
//手工初始化页表和p[M]队列 void initial(void) {
int i;
for(i=0; i
page[i].lnumber=i;
if(i
cout
cin>>page[i].pnumber;
page[i].flag=1; //存在标志置1 } }
//初始化FIFO的队列 head=0;
for(i=0; i
//输出页表和FIFO队列
void print_page_and_fifoqueue(void) {
int i;
cout
cout
cout
cout
cout
cout
//模拟地址转换
int do_mmap(int laddress) {
int lnumber, ad, pnumber, paddress;
lnumber=laddress>>10; //取逻辑地址的页号lnumber
ad=laddress&0x3ff; //页内地址
pnumber=page[lnumber].pnumber; //从页表中取得块号pnumber paddress=pnumber
return paddress; }
//CPU执行一条指令,输出物理地址表示指令执行完成 void run_a_instruction(int paddress) {
cout
//执行进程的第一条指令
void run_first_instructon(int laddress) {
int lnumber, ad, pnumber, paddress;
lnumber=laddress>>10; //取逻辑地址的页号 if(page[lnumber].flag==1)
paddress=do_mmap(laddress); //形成物理地址
cout
cout
char change; cin>>change;
if(tolower(change)=='y'){ //若指令执行完时修改了页面,则置write标志位位1
page[lnumber].write=1;
print_page_and_fifoqueue(); }
cout
//页面写回磁盘
void write_to_harddisk(int j) {
cout
//缺页中断处理程序
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
cout
system(
print_page_and_fifoqueue(); }
五.实验结果
三:实验总结:
通过编写本实验,不仅理解了OS中页面置换算法,也锻炼java的awt编程能力,特别是布局设计和事件响应,编程过程中会遇到些小问题,可以通过各种途径解决,另外,编程之前要做好整体规划,最好写出来,把各个模块的功能和主要变量都写成文档,这样效率很高。编程是体力活,