动态分区分配算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机操作系统动态分区磁盘调度算法
一个好的计算机系统不仅要有足够的存储容量,较高的存取速度和稳定可靠的存储器,而且能够合理的分配和使用这些主存空间。
当用户提出申请主存空间的要求时,存储管理能够按照一定的策略分析主存的使用情况,找出足够的空间分配给申请者;当作业运行完毕,存储管理要回收作业占用的主存空间。
本实验采取可变分区存储管理方法,用常用分区管理算法模拟磁盘管理过程,以加深了解操作系统的存储管理功能。
1. 本实验是模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不实际启动装入作业。
2. 采用最先适应法、最佳适应法、最坏适应法分配主存空间。
3. 当一个新作业要求装入主存时,必须查空闲区表,从中找出一个足够大的空闲区。
若找到的空闲区大于作业需要量,这是应把它分成二部分,一部分为占用区,加一部分又成为一个空闲区。
4. 当一个作业撤离时,归还的区域如果与其他空闲区相邻,则应合并成一个较大的空闲区,登在空闲区表中。
5. 设计的模拟系统中,进程数不小于5,进程调度方式可以采用实验一中的任何一种。
6. 运行所设计的程序,输出有关数据结构表项的变化和内存的当前状态。
首次适应算法
将内存中的空闲区按照地址由低到高的顺序形成空闲区表
当一个新作业要求装入主存时,查空闲区表,从中找到第一个满足要求的空闲区,为作业分配主存空间,并将剩余空闲区按照地址由小到大的顺序插入空闲区表的合适位置,修改已分配表
当作业运行结束后,回收作业的主存空间,并与相邻空闲区合并,修改空闲区表和已分配表每次主存分配和回收后,打印空闲区表和已分配表
详细描述实验设计思想、程序结构及各模块设计思路;
详细描述程序所用数据结构及算法;
明确给出测试用例和实验结果;
为增加程序可读性,在程序中进行适当注释说明;
认真进行实验总结,包括:设计中遇到的问题、解决方法与收获等;
#include<iostream>
#include<cstdlib>
using namespace std;
const int procsize=5;
typedef struct Node{
int PId; //进程Id
int Prio; //进程优先数
int NeedRunTime; //进程需要运行时间
int Room; //进程所需空间大小
Node * next; //就绪队列中的下个就绪进程的地址
}PCB;
typedef struct{ //就绪链式队列结构体
PCB *front;
PCB *rear;
}AleadyQueue;
typedef struct Tab{ //分区表结构体
int CalledId; //调用该分区的进程Id
int TabId; //分区号
int Size; //大小
int StartAdd; //始址
char * Status; //使用状态
Tab *next; //指向下个分区
}Table;
void CinInfo(PCB P[procsize]){ //输入进程信息
cout<<"\t\t请输入5个进程,格式如下:\n\n ";
cout<<"PId 优先数运行时间所需内存大小(最好是小于20)\n";
int i=0,j=0;
for(i,j; i<procsize ; i++,j++){
cin>>P[j].PId>>P[j].Prio>>P[j].NeedRunTime>>P[j].Room;
}
}
void Sort(PCB P[procsize]){ //根据优先数由冒泡法对进程进行排序int i,j,exchange=1; //exchange表示相邻PCB是否调换
PCB Temp;
for(i=procsize;i>1&&exchange;i--){
exchange=0;
for(j=0;j<i-1;j++)
if(P[j].Prio<P[j+1].Prio){
Temp=P[j];
P[j]=P[j+1];
P[j+1]=Temp;
exchange=1;
}
}
}
AleadyQueue InitQueue(){ //就绪队列初始化函数AleadyQueue Q;
Node *p;
p=(Node *)malloc(sizeof(PCB));
if(!p)
{
cout<<"就绪队列初始化失败!\n";
exit(0);
}
else
{
Q.front=Q.rear=p;
Q.front->next=NULL;
return Q;
}
}
void EnQueue(AleadyQueue &Queue,PCB &P){ //进程入队操作函数Node *p;
p=(Node *)malloc(sizeof(PCB));
if(!p)
cout<<"分配节点失败!\n";
else {
*p=P;
p->next=NULL;
Queue.rear->next=p;
Queue.rear=p;
}
}
void EnQueue1(AleadyQueue &Queue,PCB &P){ //进程入队操作函数Node *p;
p=(Node *)malloc(sizeof(PCB));
if(!p)
cout<<"分配节点失败!\n";
else {
*p=P;
p->next=NULL;
Queue.rear->next=p;
Queue.rear=p;
}
}
PCB OutQueue(AleadyQueue &Q){ //进程出队操作函数Node *P;
P=(Node *)malloc(sizeof(PCB));
if(Q.front->next!=NULL){
P=Q.front->next;
Q.front->next=P->next;
}
return *P;
}
PCB OutQueue1(AleadyQueue &Q){ //进程出队操作函数Node *P;
P=(Node *)malloc(sizeof(PCB));
if(Q.front->next!=NULL){
P=Q.front->next;
Q.front->next=P->next;
}
return *P;
}
void printinfo(AleadyQueue Q){ //打印就绪队列的情况cout<<"目前就绪队列进程情况如下:\n";
cout<<"PId\t\tPriority\t\tNeedTime\t\tRoom\n";
Q.front=Q.front->next;
while(1){
if(Q.front!=NULL){
cout<<Q.front->PId<<"\t\t"<<Q.front->Prio<<"\t\t\t";
cout<<Q.front->NeedRunTime<<"\t\t\t"<<Q.front->Room<<endl;
Q.front=Q.front->next;
}
else
break;
}
}
int chose(){ //选择所选算法int i;
cout<<"请选择:\n";
cout<<" 1、采用<首次适应>算法为进程分配内存!\n";
cout<<" 2、采用<最佳适应>算法为进程分配内存!\n";
cout<<" 3、采用<最坏适应>算法为进程分配内存!\n";
cout<<" 4、结束!\n";
cin>>i;
return i;
}
Table * CreateMMTable(){ //定义主存分区表
Table * FT; //用尾插入法
Table * R;
Table * P;
FT=(Table *)malloc(sizeof(Tab));
R=FT;
FT->next=NULL;
int num=0;
int LastAdd=0;
int LastSize=1;
while(1){
P=(Table *)malloc(sizeof(Tab));
P->CalledId=0; //被调用的进程调Id初始化为0
P->TabId=num; //主存分区号
P->Size=3*num+1; //分区大小
P->StartAdd=LastAdd+LastSize; //分区始址
P->Status="Free"; //分区状态
num++; //分区号加1
LastAdd=P->StartAdd; //重新定义LastAdd为上次的StartAdd
LastSize=P->Size; //同上
P->next=NULL;
R->next=P;
R=P;
if(P->StartAdd==93) //内存初始化完毕
break;
}
return FT;
}
Table * CreateUsedTable(){ //创建已分配表
Table * T;
T=(Table *)malloc(sizeof(Tab));
T->next=NULL;
return T;
}
void CoutMMTable(Table * FTL){ //打印主存表情况cout<<"主存表情况:\n";
cout<<"分区号\t\t"<<"分区始址\t"<<"分区大小\t"<<"状态\n";
FTL=FTL->next;
while(1){
cout<<FTL->TabId<<"\t\t"<<FTL->StartAdd<<"\t\t";
cout<<FTL->Size<<"\t\t";
cout<<FTL->Status<<endl;
FTL=FTL->next;
if(FTL->next==NULL)
break;
}
}
void CoutFreeTable(Table * FTL){ //打印空闲区表cout<<"空闲区表情况:\n";
cout<<"分区号\t\t"<<"分区始址\t"<<"分区大小\t"<<"状态\n";
FTL=FTL->next;
while(1){
cout<<FTL->TabId<<"\t\t"<<FTL->StartAdd<<"\t\t";
cout<<FTL->Size<<"\t\t";printf("%s\n",FTL->Status);
FTL=FTL->next;
if(FTL->next==NULL)
break;
}
}
void CoutUsedTable(Table * UTL){ //打印已分配表cout<<"已分配表情况:\n";
cout<<"分区号\t\t"<<"分区始址\t"<<"分区大小\t"<<"状态\n";
UTL=UTL->next;
while(1){
if(UTL->Status=="Used"){
cout<<UTL->TabId<<"\t\t"<<UTL->StartAdd<<"\t\t";
cout<<UTL->Size<<"\t\t";printf("%s\n",UTL->Status);
}
UTL=UTL->next;
if(UTL->next==NULL)
break;
}
}
int DistribMM(Table * MMTableList,PCB Temp,Table * FTL,Table * UTL){//分配一块一定大小的内存
Table *P;
Table * TempMM; //需要改为已分配节点的上一个节点TempMM=MMTableList;
Table * TTT;
TTT=MMTableList->next;
while(1){ //查找满足大小的分区节点
if(TTT->Size>=Temp.Room && TTT->Status=="Free")
break;
TTT=TTT->next;
if(TTT==NULL){
cout<<"\n\n\n\t\t\t\t警告!内存不足....\n\n\n";
return 0;
}
}//while
//以下是内存改为已分配
P=(Table *)malloc(sizeof(Tab));
while(1){
if(TempMM->next==TTT)
break;
TempMM=TempMM->next;
}
P->next=TempMM->next;
TempMM->next=P;
P->StartAdd=TTT->StartAdd;
P->Size=Temp.Room;
P->CalledId=Temp.PId;
P->TabId=TTT->TabId;
P->Status="Used";
P=P->next;
while(P!=NULL){
(P->TabId)++;
P=P->next;
}
FTL=FTL->next;
while(1){ //将空闲分区对应的首地址更改if(FTL->StartAdd==TTT->StartAdd)
break;
FTL=FTL->next;
}
TTT->StartAdd=FTL->StartAdd=TTT->StartAdd+Temp.Room;//空闲表的首地址=原来+Room TTT->Size=FTL->Size=TTT->Size-Temp.Room;
while(FTL!=NULL){
(FTL->TabId)++;
FTL=FTL->next;
}
return 2;
}
void ReturnMM(Table * MMTableList,Table * FTL,Table * UTL,PCB &Temp){ //回收一块内存MMTableList=MMTableList->next;
FTL=FTL->next;
Table *TT;
while(1){
if(MMTableList->CalledId==Temp.PId)
{
if(MMTableList->next->Status=="Free"){
MMTableList->Status="Free"; //修改内存,相邻的为Free
MMTableList->CalledId=0;
MMTableList->Size=MMTableList->Size+MMTableList->next->Size;
MMTableList->next=MMTableList->next->next;
TT=MMTableList;
while(FTL!=NULL){
if(FTL->StartAdd==TT->next->StartAdd)
break;
FTL=FTL->next;
}
FTL->Size=TT->Size;
}
if(MMTableList->next->Status!="Free")
{
MMTableList->Status="Free"; //修改内存,相邻的为USed
MMTableList->CalledId=0;
while(FTL!=NULL){
if(FTL->StartAdd==TT->next->StartAdd)
break;
FTL=FTL->next;
}
FTL->Size=TT->Size;
}
}
if(MMTableList->next==NULL)
break;
MMTableList=MMTableList->next;
}//总while
cout<<"\n";
}
int FF(Table * MMTableList,Table * FTL,Table * UTL,AleadyQueue &Q){ //首次适应算法PCB Temp;
int i; //记录分配函数的返回值0
int num=0; //记录进程首次分配内存
while(1){
Temp=OutQueue(Q);
if(num<procsize)
{
if(num==0){
cout<<"正在为"<<Temp.PId<<" 号进程分配内存......\n";
i=DistribMM(MMTableList,Temp,FTL,UTL); //分配内存函数
if(i==0) return 0; //内存不足
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表
}
if(num==1){
cout<<"正在为"<<Temp.PId<<" 号进程分配内存......\n";
i=DistribMM(MMTableList,Temp,FTL,UTL); //分配内存函数
if(i==0) return 0;
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表}
if(num==2){
cout<<"正在为"<<Temp.PId<<" 号进程分配内存......\n";
i=DistribMM(MMTableList,Temp,FTL,UTL); //分配内存函数
if(i==0) return 0; // printf("y余朝水\n");
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表}
if(num==3){
cout<<"正在为"<<Temp.PId<<" 号进程分配内存......\n";
i=DistribMM(MMTableList,Temp,FTL,UTL); //分配内存函数
if(i==0) return 0;
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表}
if(num==4){
cout<<"正在为"<<Temp.PId<<" 号进程分配内存......\n";
i=DistribMM(MMTableList,Temp,FTL,UTL); //分配内存函数
if(i==0) return 0;
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表}
}
cout<<"正在执行"<<Temp.PId<<" 号进程.....\n"; //队首调度完毕并出队
Temp.Prio--; //进程优先数减1
Temp.NeedRunTime--; //进程还需运行时间减1
cout<<"\t\t\t目前进程"<<Temp.PId<<"的优先数: "<<Temp.Prio;
cout<<" 还需运行时间: "<<Temp.NeedRunTime<<endl;
num++;
if(Temp.NeedRunTime==0) { //判断是否进程运行完毕,如果运行时间为0,则不再入队
cout<<"\n进程"<<Temp.PId<<" 运行完成!\n";
cout<<"正在回收内存......\n";
if(Temp.PId==5)return 1;
ReturnMM(MMTableList,FTL,UTL,Temp); //回收内存
CoutMMTable(MMTableList); //打印主存情况
CoutFreeTable(FTL); //打印空闲分区表
CoutUsedTable(MMTableList); //打印已分配表
printinfo(Q);
if(Q.front->next==NULL) //判断就绪队列是否为空
break;
}
else
EnQueue(Q,Temp); //运行时间不为0,还需入队等待下一个时间片再次执行
}
return 2;
}
int BF(Table * MMTableList,Table * FTL,Table * UTL,AleadyQueue &Q2){ //最佳适应算法PCB P[procsize]; //定义五个进程
CinInfo(P); //输入进程信息
Sort(P); //根据优先数的大小进行排序,形成进程数组P
Q2=InitQueue(); //就绪队列初始化
for(int k=0; k<procsize; k++)
EnQueue(Q2,P[k]);
int i; //记录分配函数的返回值0
int num=0;
PCB Temp;
while(1){
Temp=OutQueue1(Q2);
if(num<procsize)
{
if(num==0)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==1)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==2)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==3)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==4)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
}
cout<<"正在执行"<<Temp.PId<<" 号进程.....\n"; //队首调度完毕并出队
Temp.Prio--; //进程优先数减1
Temp.NeedRunTime--; //进程还需运行时间减1
cout<<"\t\t\t目前进程"<<Temp.PId<<"的优先数: "<<Temp.Prio;
cout<<" 还需运行时间: "<<Temp.NeedRunTime<<endl;
num++;
if(Temp.NeedRunTime==0) { //判断是否进程运行完毕,如果运行时间为0,则不再入队
cout<<"\n进程"<<Temp.PId<<" 运行完成!\n";
cout<<"正在回收内存......\n";
cout<<"...........................\n\n";
if(Q2.front->next==NULL) //判断就绪队列是否为空
break;
}
else
EnQueue1(Q2,Temp); //运行时间不为0,还需入队等待下一个时间
片再次执行
}
return 1;
}
int WF(Table * MMTableList,Table * FTL,Table * UTL,AleadyQueue &Q2){ //最坏适应算法PCB P[procsize]; //定义五个进程
CinInfo(P); //输入进程信息
Sort(P); //根据优先数的大小进行排序,形成进程数组P Q2=InitQueue(); //就绪队列初始化
for(int k=0; k<procsize; k++)
EnQueue(Q2,P[k]);
int i; //记录分配函数的返回值0
int num=0;
PCB Temp;
while(1){
Temp=OutQueue1(Q2);
if(num<procsize)
{
if(num==0)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==1)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==2)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==3)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
if(num==4)
{cout<<"正在为"<<Temp.PId<<"进程分配内存......\n";
cout<<"...........................\n\n";}
}
cout<<"正在执行"<<Temp.PId<<" 号进程.....\n"; //队首调度完毕并出队
Temp.Prio--; //进程优先数减1
Temp.NeedRunTime--; //进程还需运行时间减1
cout<<"\t\t\t目前进程"<<Temp.PId<<"的优先数: "<<Temp.Prio;
cout<<" 还需运行时间: "<<Temp.NeedRunTime<<endl;
num++;
if(Temp.NeedRunTime==0) { //判断是否进程运行完毕,如果运行时间
为0,则不再入队
cout<<"\n进程"<<Temp.PId<<" 运行完成!\n";
cout<<"正在回收内存......\n";
cout<<"...........................\n\n";
if(Q2.front->next==NULL) //判断就绪队列是否为空
break;
}
else
EnQueue1(Q2,Temp); //运行时间不为0,还需入队等待下一个时间片再次执行
}
return 2;
}
void main(){
AleadyQueue Q1; //定义一个就绪队列
AleadyQueue Q2;
AleadyQueue Q3;
PCB P[procsize]; //定义五个进程
CinInfo(P); //输入进程信息
Sort(P); //根据优先数的大小进行排序,形成进程数组P Q1=InitQueue(); //就绪队列初始化
Q2=InitQueue();
Q3=InitQueue();
for(int k=0; k<procsize; k++)
EnQueue(Q1,P[k]); //首次排好序的就绪进程入队,
//进程依次等待处理机调度
for(k=0; k<procsize; k++)
EnQueue(Q2,P[k]);
for(k=0; k<procsize; k++)
EnQueue(Q3,P[k]);
printinfo(Q1); //打印当前就绪队列的情况
Q3=Q2=Q1;
Table * MMTableList; //主存分区表
Table * MM;
Table * FreeTableList; //空闲分区表
Table * UsedTableList; //已分配分区表
MMTableList=CreateMMTable(); //创建主存分区表
MM=CreateMMTable();
FreeTableList=CreateMMTable(); //创建空闲分区表(初始化时和内存分区表相同)UsedTableList=CreateUsedTable(); //创建已分配表
CoutMMTable(MMTableList); //打印主存分区表
int i; //记录0,内存不足
int j; //记录所选算法
while(1){
j=chose(); //判断所选算法,所需操作(FF、BF、WF)
if(j==1)
i=FF(MM,FreeTableList,UsedTableList,Q1);//首次适应算法
if(i==0)
exit(0); //内存不足
if(j==2)
i=BF(MM,FreeTableList,UsedTableList,Q2);//最佳适应算法
if(i==0)
exit(0); //内存不足
if(j==3)
i=WF(MM,FreeTableList,UsedTableList,Q3);//最坏适应算法
if(i==0)
exit(0); //内存不足
if(j==4)
break; //结束内存分配
}
cout<<"\n\n\n-----------------------------------欢迎使用!------------------------------------\n\n\n\n\n"; }。