一、实验目的
连续内存分配方式会形成许多“碎片”,虽然可以通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无需再进行“紧凑”。基于这一思想而产生了离散分配方式。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
在分页存储管理方式中,如果不具备页面兑换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具备支持虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。
本实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。
二、实验要求
1、用C语言或Java语言编写程序模拟操作系统对内存的基本分页存储管理方式
2、程序要能正确对“内存”进行“分配”和“回收”,能接受用户的输入,显示内存的分配情况,并有一定的容错能力。
3、每个人独立按时完成实验内容。
三、实验方法
#include<iostream> #include<iostream.h> #include<iomanip.h> #include<ctype.h> #define N 6 #define M 4 struct{ int lnumber; int flag; int pnumber; int write; int dnumber; }page[N]; int p[M]; int head; void initial(void); intdo_mmap(int); void do_page_fault(int); void run_first_instructon(int); void run_a_instruction(int); void print_page_and_fifoqueue(void); main() { int laddress,paddress; int lnumber,ad,pnumber; print_page_and_fifoqueue(); run_first_instructon(0x0000); cout<<"输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl; cin>>laddress; while(laddress>32767){ cout<<"输入错误! 请重新输入下一条指令的逻辑地址(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); cout<<"此指令执行是否修改所在页lnumber="<<lnumber<<"(y/n?) "; char change; cin>>change; if(tolower(change)=='y'){ page[lnumber].write=1; print_page_and_fifoqueue(); } } else{ cout<<lnumber<<"输出该页的页号--表示硬件产生缺页中断"<<endl; do_page_fault(lnumber); continue; } cout<<"输入下一条指令的逻辑地址((0~32767),-1 to end) "; cin>>laddress; while(laddress>32767){ cout<<"worse(0~32767)(-1 to end)"<<endl; cin>>laddress; } } cout<<"进程运行结束!"<<endl; system("PAUSE"); return 0; } void initial(void) { int i; for(i=0; i<=5; i++){ page[i].lnumber=i; if(i<=M-1){ cout<<"输入页号为"<<i<<" 所在内存的物理块号(预装入前四个页面):"; cin>>page[i].pnumber; page[i].flag=1; } } head=0; for(i=0; i<=M-1; i++) p[i]=i; } voidprint_page_and_fifoqueue(void) { int i; cout<<"输出页表! "; 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<<"输出FIFO对列: "; cout<<setw(10)<<"NO"<<setw(40)<<"page(已在主存的页号lnumber) "; cout<<"head="<<head<<endl; for(i=0; i<=M-1;i++) cout<<setw(10)<<i<<setw(15)<<p[i]<<endl; } intdo_mmap(intladdress) { intlnumber, ad, pnumber, paddress; lnumber=laddress>>10; ad=laddress&0x3ff; pnumber=page[lnumber].pnumber; paddress=pnumber<<10|ad; returnpaddress; } voidrun_a_instruction(intpaddress) { cout<<paddress<<" 输出物理地址--表示指令执行完成"<<endl; } voidrun_first_instructon(intladdress) { intlnumber, 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'){ page[lnumber].write=1; print_page_and_fifoqueue(); } cout<<"********第一条指令执行完成(地址为0x0000)***********"<<endl; } voiddo_page_fault(intlnumber) { int j; j=p[head]; p[head]=lnumber; head=(head+1)%M; if(page[j].write==1) write_to_harddisk(j); page[j].flag=0; page[lnumber].flag=1; page[lnumber].write=0; page[lnumber].pnumber=page[j].pnumber; cout<<lnumber<<"输出该页--表示该页调入了主存"<<endl; cout<<"按任意键将查看“页面置换”之后的页表page[N]和FIFO队列信息"<<endl; system("PAUSE"); print_page_and_fifoqueue(); }
四、实验总结
实验比较难以理解,因为学的知识太多,并不能什么都学精,希望自己可以慢慢地深入了解。