操作系统主存储器空间的分配和回收.docx
《操作系统主存储器空间的分配和回收.docx》由会员分享,可在线阅读,更多相关《操作系统主存储器空间的分配和回收.docx(28页珍藏版)》请在冰豆网上搜索。
操作系统主存储器空间的分配和回收
实习四主存储器空间的分配和回收
一,实习题目
本实习模拟在两种存储管理方式下的主存分配和回收。
第一题:
在可变分区管理方式下采用最先适应算法实现主存分配和实现主存回收。
[提示]:
可变分区方式是按作业需要的主存空间大小来分割分区的。
当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,假设有,则按需要量分割一个分区分配给该作业;假设无,则作业不能装入。
随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。
例如:
0
5k
10k
14k
26k
32k
128k
操作系统
作业1
作业3
空闲区
作业2
空闲区
为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:
起址
长度
状态
第一栏
14K
12K
未分配
第二栏
32K
96K
未分配
空表目
空表目
其中,起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白〔无效〕,可用来登记新的空闲区〔例如,作业撤离后,它所占的区域就成了空闲区,应找一个“空表目”栏登记归还区的起址和长度且修改状态〕。
由于分区的个数不定,所以空闲区说明表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。
上述的这张说明表的登记情况是按提示〔1〕中的例所装入的三个作业占用的主存区域后填写的。
(2)当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。
有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:
一部分分给作业占用;另一部分又成为一个较小的空闲区。
为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。
为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。
为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。
(3)采用最先适应算法〔顺序分配算法〕分配主存空间。
按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。
当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。
由于本实习是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。
最先适应分配算法如图4-1。
(4)当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。
例如,在提示〔1〕中列举的情况下,如果作业2撤离,归还所占主存区域时,应与上、下相邻的空闲区一起合成一个大的空闲区登记在空闲区说明表中。
归还主存时的回收算法如图4-2。
(5)请按最先适应算法设计主存分配和回收的程序。
然后按〔1〕中假设主存中已装入三个作业,且形成两个空闲区,确定空闲区说明表的初值。
现有一个需要主存量为6K的作业4申请装入主存;然后作业3撤离;再作业2撤离。
请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。
二,本实验用到的一些数据结构有:
typedefstructNODE
{
charname;//名称
floatstart;//起始位置
floatend;//大小
intflag;//是否分配的标志
}NODE;
NODEOS[COUNT];//数组
三,流程图
四,源代码
#include
#include
#defineCOUNT512
typedefstructNODE
{
charname;//名称
floatstart;//起始位置
floatend;//大小
intflag;//是否分配的标志
}NODE;
NODEOS[COUNT];//数组
intcount;//被分成的块数统计
intapplyfree;
floatnumb;
charc;
//先对数组进行初始化,使没有分配的名称为P
voidinit()
{
count=1;
OS[0].name='P';
OS[0].start=0;
OS[0].end=COUNT;
OS[0].flag=1;
}
//对数组的插入操作
voidinsert(intm,floatst,floaten)
{
inti;
count++;
for(i=count;i>m+1;i--)
{
OS[i]=OS[i-1];
}
OS[m].start=st;
OS[m].end=en;
}
//移动操作,即对数组的删除操作
voidmove(intm)
{
inti;
for(i=m;i{
OS[i]=OS[i+1];
}
count--;
}
//如果相邻块都没有分配,则要合并到一起
voidrremove(intm,floatst,floaten)
{
if(!
OS[m-1].flag&&!
OS[m+1].flag)
{
OS[m].name='P';
OS[m].flag=1;
}
if(OS[m-1].flag)
{
OS[m-1].end=OS[m-1].end+en;
move(m);
}
if(OS[m+1].flag)
{
OS[m].end=OS[m].end+OS[m+1].end;
OS[m].name='P';
OS[m].flag=1;
move(m+1);
}
}
//打印输出
voidshow()
{
inti;
printf("名称标识起址长度状态\n");
for(i=0;i{
if(OS[i].flag)
printf("P");
else
printf("%c",OS[i].name);
printf("%d%1.0f%1.0f",i,OS[i].start,OS[i].end);
if(OS[i].flag)
printf("未分配\n");
else
printf("已分配\n");
}
}
//从键盘输入数据
voidputin()
{
printf("请输入申请或者释放的进程名称及资源数量:
\n");
rewind(stdin);
scanf("%c",&c);
scanf("%d",&applyfree);
scanf("%f",&numb);
}
intapply()
{
inti=0;
intapplyflag=0;
intfreeflag=0;
if(applyfree)//提出申请资源
{
while(!
applyflag&&i{
if(OS[i].end>=numb&&OS[i].flag)
{
if(OS[i].end==numb)
{
OS[i].name=c;
OS[i].flag=0;
}
else
{
insert(i+1,OS[i].start+numb,OS[i].end-numb);
OS[i+1].flag=1;
OS[i+1].name='P';
OS[i].start=OS[i].start;
OS[i].name=c;
OS[i].end=numb;
OS[i].flag=0;
}
applyflag=1;
}
i++;
}
if(applyflag)
{
printf("申请成功!
\n");
return1;
}
else
{
printf("申请失败!
没有足够大的空闲空间。
\n");
return0;
}
}
else//提出释放资源
{
while(!
freeflag&&i{
if(OS[i].name==c)
{
if(OS[i].end==numb)
{
rremove(i,OS[i].start,OS[i].end);
}
else
{
if(OS[i].end>numb)
{
insert(i+1,OS[i].start+numb,OS[i].end-numb);
OS[i+1].name='P';
OS[i+1].flag=0;
OS[i].end=numb;
OS[i].flag=1;
if(OS[i-1].flag)
{
rremove(i,OS[i].start,OS[i].end);
}
}
else
{
printf("释放失败,因为正使用的数量小于要求释放的数量。
\n");
return0;
}
}
freeflag=1;
}
i++;
}
if(freeflag)
{
printf("释放成功!
\n");
return1;
}
else
{
printf("释放失败!
未找到匹配的进程名称。
\n");
return0;
}
}
}
voidmain()
{
init();
show();
while
(1)
{
putin();
apply();
show();
}
}
五,执行结果
空闲区说明表的初始状态
作业4的申请量以及为作业4分配后的空闲区说明表状态
作业3和作业2的归还量以及回收作业3,作业2所占主存后的空闲区说明表
第二题:
在分页式管理方式下采用位示图来表示主存分配情况,实现主存空间的分配和回收。
[提示]:
(1)分页式存储器把主存分成大小相等的假设干块,作业的信息也按块的大小分页,作业装入主存时可把作业的信息按页分散存放在主存的空闲块中,为了说明主存中哪些块已经被占用,哪些块是尚未分配的空闲块,可用一张位示图来指出。
位示图可由假设干存储单元来构成,其中每一位与一个物理块对应,用0/1表示对应块为空闲/已占用。
(2)假设某系统的主存被分成大小相等的64块,则位示图可用8个字节来构成,另用一单元记录当前空闲块数。
如果已有第0,1,4,5,6,9,11,13,24,31,共10个主存块被占用了,那么位示图情况如下:
字位
节数
号
0
1
2
3
4
5
6
7
0
1
1
0
0
1
1
1
0
1
0
1
0
1
0
1
0
0
2
0
0
0
0
0
0
0
0
3
1
0
0
0
0
0
0
1
4
0
0
0
0
0
0
0
0
5
0
0
0
0
0
0
0
0
6
0
0
0
0
0
0
0
0
7
0
0
0
0
0
0
0
0
图4-1最先适应分配模拟算法
图4-2主存回收算法
(3)当要装入一个作业时,根据作业对主存的需要量,先查当前空闲块数是否能满足作业要求,假设不能满足则输出分配不成功。
假设能满足,则查位示图,找出为“0”的一些位,置上占用标志“1”,从“当前空闲块数”中减去本次占用块数。
按找到的计算出对应的块号,其计算公式为:
块号=j⨯8+i
其中,j表示找到的是第n个字节,I表示对应的是第n位。
根据分配给作业的块号,为作业建立一张页表,页表格式:
页号
块号
0
1
2
(4)当一个作业执行结束,归还主存时,根据该作业的页表可以知道应归还的块号,由块号可计算出在位示图中的对应位置,把对应位的占用标志清成“0”,表示对应的块已成为空闲块。
归还的块数加入到当前空闲块数中。
由块号计算在位示图中的位置的公式如下:
字节号j=[块号/8]〔[]表示取整〕
位数i={块号/8}〔{}表示取余〕
(5)设计实现主存分配和回收的程序。
假定位示图的初始状态如〔2〕所述,现有一信息量为5页的作业要装入,运行你所设计的分配程序,为作业分配主存且建立页表〔格式如〔3〕所述〕。
然后假定有另一作业执行结束,它占用的块号为第4,5,6和31块,运行你所设计的回收程序,收回作业归还的主存块。
要求能显示和打印分配或回收前后的位示图和当前空闲块数,对完成一次分配后还要显示或打印为作业建立的页表。
二,源代码
#include
#defineN64//物理块数
#defineM100000//最多输入文件数
structfile//文件结构体,包含文件号,文件页长,页号,几页号对应的块号
{
intfilenum;
intyechang;
intyenum;
intkuainum;
};
structfilefl[N];//文件结构体数组
voidput(inta[8][8])//输出位示图
{
inti,j;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
printf("\t%d",a[i][j]);
printf("\n");
}
}
voidhuishou(inta[8][8],intb)//回收规定的页面
{
intc[4]={4,5,6,31};
inti,j,k,empty;
inth[4];
for(k=0;k<4;k++)
{
h[k]=c[k];
i=c[k]/8;
j=c[k]%8;
a[i][j]=0;
}
printf("\n需要回收的页号和块号分别为:
\n");
printf("页号\t块号\n");
for(k=0;k<4;k++)
{
printf("%d\t%d\n",k,h[k]);
}
printf("回收后的页表位示图为:
\n");
put(a);
empty=0;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i][j]==1)
empty+=1;
}
}
empty=64-empty;
printf("剩余的块数:
%d\n",empty);
}
voidshixian(inta[8][8],intb)//实现存储空间的分配与回收
{
inti,j,k,x,y,m,empty,full,fileshu,kuainum,h[N],g[N][N];
intcishu=0,hang=0,lie=0,filenum=0,wenjianshu=0;
intp[M]={-1};
intjian=0;
empty=b;
beg:
printf("请输入需要装入的文件的页数:
");
scanf("%d",&m);
printf("\n");
cishu=0;
if(emptyprintf("需要装入的页数大于页表中的空闲页数,分配失败\n");
else
{
wenjianshu+=1;
for(i=1;i<=wenjianshu;i++)
{
if(fl[i].yechang==0)
filenum=i;
else
filenum+=1;
}
h[filenum]=m;
fl[filenum].filenum=filenum;
for(i=0;i{
fl[filenum].yenum=i;
}
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i][j]==0)
{
a[i][j]=1;
kuainum=i*8+j;
cishu+=1;
fl[filenum].yenum=cishu;
fl[filenum].kuainum=kuainum;
g[filenum][cishu]=kuainum;
}
if(cishu>=m)
break;
}
if(cishu>=m)
break;
}
fl[filenum].yechang=m;
printf("文件号:
%d\t文件页长:
%d\n",fl[filenum].filenum,
fl[filenum].yechang);
printf("页号\t块号\n");
for(i=0;i{
printf("%d\t",fl[filenum].yenum-m+i);
printf("%d\n",g[filenum][i+1]);
}
full=0;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i][j]==1)
full+=1;
}
}
empty=64-full;
printf("剩余的块数:
%d\n",empty);
printf("分配后的页表位示图为:
\n");
put(a);
}
printf("继续装入文件请输入1,回收页面请输入2,输入其他键结束:
");
scanf("%d",&y);
if(y==1)
gotobeg;
elseif(y==2)
gotoaeg;
else
gotoend;
aeg:
printf("请输入需要回收的文件号大于0且不在以下数集中的数---\t");
for(i=1;i<=jian;i++)
{
if(p[jian]!
=-1)
printf("%d\t",p[jian]);
}
printf("\n输入的需要回收的页数为:
");
scanf("%d",&fileshu);
if(wenjianshuprintf("你输入的文件号不存在!
\n");
if(fileshu<=0)
printf("你输入的文件号不存在!
\n");
else
{
k=g[fileshu][1];
filenum=fileshu;
for(x=0;x{
k=g[fileshu][x+1];
i=k/8;
j=k%8;
a[i][j]=0;
}
printf("回收页面后的页表位示图为:
\n");
put(a);
empty=0;//显示空闲页数
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i][j]==1)
empty+=1;
}
}
empty=64-empty;
printf("剩余的块数:
%d\n",empty);
fl[fileshu].yechang=0;
jian+=1;
p[jian]=fileshu;
}
printf("继续装入页面请输入1,回收页面请输入2,输入其他键结束:
");
scanf("%d",&y);
if(y==1)
gotobeg;
elseif(y==2)
gotoaeg;
else
gotoend;
end:
printf("\n");
huishou(a,empty);
}
voidmain()
{
inti,j,b,m,n;
intc[N]={0,1,4,5,6,9,11,13,24,31};
inta[8][8]={0};
for(m=0;m<10;m++)
{
i=c[m]/8;
j=c[m]%8;
a[i][j]=1;
}
printf("初始化的位示图是:
\n");
put(a);
b=0;
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
if(a[i][j]==1)
b=b+1;
}
}
n=64-b;
printf("剩余的块数:
%d\n",n);
shixian(a,n);
}
三,执行结果