一、实验目的
连续内存分配方式会形成许多“碎片”,虽然可以通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无需再进行“紧凑”。基于这一思想而产生了离散分配方式。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
在分页存储管理方式中,如果不具备页面兑换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具备支持虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。
本实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。
二、实验要求
1、用C语言或Java语言编写程序模拟操作系统对内存的基本分页存储管理方式
2、程序要能正确对“内存”进行“分配”和“回收”,能接受用户的输入,显示内存的分配情况,并有一定的容错能力。
3、每个人独立按时完成实验内容。
三、实验内容
本实验假定内存空间已经按块划分,目标程序无需关心内存块大小等底层细节,只需按算法对内存块进行分配即可。程序应该实现以下功能:
1、内存初始化。假定内存块共有N个,初始化后的内存空间应该有一部分已经被使用,这可以用随机数或程序内部的其他算法完成。
2、程序应该能接受用户输入的进程信息,并为之分配内存,返回分配结果(成功或失败),注意,此处应该考虑到不合法的输入并进行相应处理。
3、程序能回收用户指定的进程所占用的内存空间,因此,程序可能需要为每个进程分配一个唯一的进程号并给出详细的提示信息。
4、能直观合理地显示内存分配情况。
5、程序界面友好,便于操作和查看运行结果。
#include <iostream> using namespace std; #define INVALID -1 //定义结构类型 struct pl_type { //页表结构 int pn; //页号 int fn; //页帧号 int time; //访问时间 }; struct fl_type { //页帧结构 int pn; //页号 int fn; //页帧号 struct fl_type *next;//链接指针 }; //定义结构变量 pl_type pl[512]; fl_type fl[512],*free_head,*busy_head,*busy_tail; int page[512]; //访问串(存放每条指令的页号) int TOTAL_PAGES; //访问串长度 int diseffect; //页故障数 //初始化函数:初始化页表和页帧链 //形参total_pf为分配给用户进程的内存页帧数 void initialize(int total_pf) { int i; diseffect=0; //页故障数初始化为0 //建立空页表 for(i=0;i<512;i++) { pl[i].pn=i; //页号 pl[i].fn=INVALID; //页帧号为-1,(开始时,页还未装入到页帧) pl[i].time=-1; } //建立空闲页帧链 for(i=0;i<total_pf;i++) { fl[i-1].next=&fl[i]; //建立fl[i-1]和fl[i]间的链接 fl[i-1].fn=i-1; } fl[total_pf-1].next=NULL; //链表末尾为空指针 fl[total_pf-1].fn=total_pf-1; //末尾结点的页帧号 free_head=&fl[0]; //空闲页帧链头指针指向fl[0] } void LRU(int total_pf) { int i,j,min,minj,present_time; present_time=0; initialize(total_pf); for(i=0;i<TOTAL_PAGES;i++) { if(pl[page[i]].fn==INVALID) { //页故障 diseffect++; if(free_head==NULL) { //无空闲页帧 min=32767; for(j=0;j<TOTAL_PAGES;j++) { //找time的最小值 if(min>pl[j].time && pl[j].fn!=INVALID) { min=pl[j].time; minj=j; } } free_head=&fl[pl[minj].fn]; //腾出一页帧 pl[minj].fn=INVALID; pl[minj].time=-1; free_head->next=NULL; } pl[page[i]].fn=free_head->fn; //有空闲页帧,改为有效 pl[page[i]].time=present_time; //time置为当前时间 free_head=free_head->next; //空闲页帧链头指针前移 } else pl[page[i]].time=present_time; //time置为当前时间 present_time++; } cout<<"LRU:"<<diseffect<<"("<<(float)diseffect/TOTAL_PAGES<<")"; } void getRefstring(void) { int i; cout<<"输入的访问串以'-1'结束!"<<endl; cout<<"请输入访问串:"; for(i=0;i<512;i++) { cin>>page[i]; if(page[i]==-1) break; } TOTAL_PAGES=i; //访问串大小 cout<<"访问串大小:"<<i<<endl<<"访问串为:"; for(i=0;i<TOTAL_PAGES;i++) cout<<page[i]<<" "; cout<<endl<<endl; } int main() { int f; getRefstring(); for(f=2;f<=TOTAL_PAGES;f++) { //页帧数从3个页帧到TOTAL_PAGES个页帧 cout<<"若分配给进程"<<f<<"页帧,页故障数(缺页率):"; LRU(f); cout<<endl; } system("pause"); return 0; }
四 结论与体会
这次是最后一次的作业了,程序代码到现在我还是很多不懂,这次的作业加深了对存储管理方面的理解。