操作系统一周实验:连续式与分页式主存管理的模拟实现
3.1 实验目的
模拟在连续分配与分页管理两种方式下,主存空间的分配与回收,帮助学生加深了解存
储器管理的工作过程。
注意,该实验为模拟实验,并不要求进行真正的内存分配与回收,主要是编写程序模拟
其中过程即可。
3.2 实验内容
3.2.1 连续式分配
1、 在连续分配方式下,设计一个动态分区分配与回收的内存管理程序。
2、 动态分区分配按作业需要的主存大小来分割分区。当要装入一个作业时,根据作业需要
的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;
若无,则作业不能装入(此处事否有必要这样安排,如果我动态创建链表,就没有必要
这样了……)。
3、 设置一张全局分区状态表说明当前内存分配状态,例如下所示:(大小自行设定)
操作系统区
作业 1
作业 3
空闲区
作业 2
空闲区
0
5k
10k
14k
26k
32k
640k
4、 设置一张空闲分区表描述当前空闲分区分布状况,可采用数组或链表来实现,数组可参
考以下格式:
第一栏
起
址
14 K
长
度
12 K
状
态
未 分 配
第二栏
32 K
96 K
说明:
未 分 配
空 表 目
空 表 目
起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区
域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来
登记新的空闲区。
5、 在作业撤销后,系统需要回收分区。在空闲分区表中找到一个空表目登记回收分区的起
址和长度,并且修改表目状态为未分配。
注意:由于分区的个数不定,所以空闲分区表中应有适量的状态为“空表目”的登记栏
目,否则造成表格“溢出”无法登记。
6、 在回收分区时,应考虑相邻空闲分区合并。
7、 在完成一次作业装入后,都需要输出:本次分配的分区起址与长度,全局分区状态表,
空闲分区表的内容。若在分配中发生分割,需要说明分割后新空白分区的起址与长度。
8、 在完成一次作业撤销后,都需要输出:本次回收的分区起址与长度,全局分区状态表,
空闲分区表的内容。若发生相邻空闲分区合并,需要说明哪几个分区合并在一起,合并
后的起址与长度
3.2.2 分页式管理
1、 设计一个基本分页存储管理程序
2、 分页式存储器把主存分成大小相等的若干块,作业的信息也按块的大小分页,作业装入
主存时按页分散存放在主存的空闲块中。
3、 系统用一张块表记录物理块分配的情况,如下图所示,其中状态 0 表示未分配,1 表示
已分配。另外增加一个空闲块数,记录当前可用的物理块总数。
第 0 块
第 1 块
第 2 块
第 3 块
第 4 块
状态
1
1
0
1
0
4、 需要为每个作业设置一张页表,记录页号与块号的对应关系。
页 号
块 号
168
72
56
0
1
2
5、 作业装入内存时,分配过程如下:
a) 将空闲块数乘上每块空间,计算出可用空间总数,然后与作业需要空间比较,若不
能满足需要,提示不能装入。
b) 若能满足需要,为作业创建页表,在块表中寻找足够的空白块,将页号与块号一一
对应,并填入页表。同时修改块表中各个块的状态
c) 修改空闲块数,记录剩下空白块总数。
6、 作业撤销后,需要回收物理块,回收过程如下:
a) 根据页表,修改块表中对应各个物理块的状态
b) 修改空闲块数,记录回收后空白块总数。
c) 撤销页表
7、 每次作业装入或回收,都需要输出块表、页表的内容,发生变化的块号,以及空闲块数。
若块表太大,可以用二维表格的方式输出,或只输出发生变化的块号。
3.3 实验要求
1、根据例程,尝试采用首次适应算法、循环首次适应算法、最佳适应算法其中的一种或多
种算法实现 3.2.1 的动态分区分配。算法思想请参考课本的分区分配算法。
2、根据例程,尝试实现 3.2.1 的分区回收功能。
3、根据例程,尝试实现 3.2.2 的分页系统功能
4、至少完成上述三项实验内容中的一个。
5、自行设定内存总空间,大小单位为 KB,分页管理需要设定每个页的大小。
6、随机设置当前内存分配状态。
7、自行设计作业队列,队列中至少要有 5 个作业,设定各个作业空间大小,大小要适中。
8、输出结果要尽量详细清晰,如果输出内容比较多,可以考虑把输出结果保存到文件中,
通过文件来查看。
9、程序代码要尽量加入注释,提高程序的清晰度与可读性。
10. 在实验报告中,一方面可以对实验结果进行分析,一方面可以对两种分配方式进行比较,
分析它们的优劣。
代码见:
附件 1、
程序实现截图见:
附件 2
{
int flag;
int size;
char WorkName[10];
char detail[20];
int PageList[PageNum];
}work[PageNum];
//该作业的页表和当前状态下的块表的输出
void LayOut(int workP,int i)
{
int j;
printf("当前状态下,块表的状态\n");
for(j=0;j
int workP=-1;//workP 指向当前作业的作业号,作业安排按照数组的逻辑前后顺序分配
while(work[++workP].flag==1);
printf("请输入你的作业大小\n");
scanf("%d",&WorkSize);
if(WorkSize >(PageNum-PageUsed)*PageSize){
printf("你申请失败,超出现有的资源\n");
return ;
}
else {
numOfWork++;
work[workP].size=WorkSize;
printf("请输入作业的名字 内容\n");
scanf("%s",&work[workP].WorkName);
getchar();
scanf("%s",&work[workP].detail);
work[workP].flag=1;
}
//页面的分配
int i=0;
while(WorkSize>0)
{
int P;
P=random();
if(MemAllocate[P]==0)
{
PageUsed++;
WorkSize-=PageSize;
MemAllocate[P]=1;
work[workP].PageList[i++]=P;
} else continue;
}
printf("页面分配完毕\n");
i--;
LayOut(workP,i);
}
//删除作业
void delete_work(void)
{
int workP;
printf("请输入你要删除的作业编号\n");
scanf("%d",&workP);
if(work[workP].flag==0)
{
printf("%d 号作业不存在,请重新输入\n",workP);
return;
}
work[workP].flag=0;
for(int i=0;i<=work[workP].size/PageSize;i++) work[workP].PageList[i]=-1;
int PageSum=work[workP].size/PageSize+1;//该作业所占用的页面数
for(int i=0;i