外存空闲空间管理模块的设计与实现C语言.docx
《外存空闲空间管理模块的设计与实现C语言.docx》由会员分享,可在线阅读,更多相关《外存空闲空间管理模块的设计与实现C语言.docx(42页珍藏版)》请在冰豆网上搜索。
外存空闲空间管理模块的设计与实现C语言
外存空闲空间管理模块的设计与实现C语言(总27页)
计算机科学与应用系
课程设计报告
操作系统原理
姓名
学号
指导教师
专业
日期
成绩
题目
外存空闲空间管理模块的设计与实现
指
导
教
师
评
语
1.题目描述
文件管理要解决的重要问题之一是如何为新创建的文件分配存储空间。
其分配方法与内存的分配有诸多相似之处,即同样可采取连续分配方式或离散分配方式。
前者具有较高的文件访问速度,但可能产生较多的外存零头;后者能有效地利用外存空间,但访问速度较慢。
不论哪种分配方式,存储空间的基本分配单位都是磁盘块而非字节。
为了实现存储空间的分配,系统首先必须能记住存储空间的使用情况。
为此,系统应为分配存储空间而设置相应的数据结构;其次,系统应提供对存储空间进行分配和回收的手段。
2.设计思想
常用的文件存储空间的管理方法有:
空闲表法、空闲链表法、位示图法、成组链接法。
本次设计我用了空闲表法和位示图法来模拟实现外存空闲空间的管理。
(1)空闲表法
空闲表法属于连续分配方式,它与内存的动态分配方式雷同,它为每个文件分配一块连续的存储空间,即系统也为外存上的所有空闲区建立一张空闲表,每个空闲区对应于一个空闲表项,其中包括表项序号、该空闲区的第一个盘块号、该区的空闲盘块数等信息。
(2)位示图法
位示图是利用二进制的一位来表示磁盘中一个盘块的使用情况。
当其值为“0”时,表示对应的盘块空闲;为“1”时,表示已分配。
磁盘上所有的盘块都有一个二进制位与之对应,这样,由所有盘块所对应的位构成一个集合,成为位示图。
3.功能
本设计是模拟实现外存空闲空间的管理,用户可以选择空闲表法或者位示图法来进行文件的分配与回收并查看各个文件的存储状态。
4.数据结构和算法设计
4.1数据结构
(1)空闲表法数据结构
分区表目结构定义structPartition。
(2)位示图法数据结构
空闲区结构体定义free_link、申请空间作业结构体定义office、相关位示图操作的结构体定义work。
4.2算法设计
(1)空闲表法算法设计
空闲盘区的分配采用首次适应算法。
在系统为某新创建的文件分配空闲盘块时,先顺序地检索空闲表的各表项,直至找到第一个其大小能满足要求的空闲区,再将该盘区分配给用户,同时修改空闲表。
系统在对用户所释放的存储空间进行回收时,要考虑回收区是否与空闲表中插入点的前区和后区相邻接,对相邻接者予以合并。
(2)位示图法算法设计
盘块分配时,顺序扫描位示图,从中找出一个或一组其值为“0”的二进制位,转换成与之对应的盘块号,然后修改位示图。
盘块回收时,将回收盘块的盘块号转换成位示图的行号和列号,修改位示图。
5.流程图
5.1空闲表法流程图
(1)盘块分配流程图,如图5-1所示。
否
否是
是
否
是
(2)盘块回收流程图,如图5-2所示。
否
是
否否
是是
5-2空闲表法盘块回收流程图
5.2位示图法流程图
(1)盘块分配流程图,如图5-3所示。
否
是
否
是
否
是
图5-3位示图法盘块分配流程图
(2)盘块回收流程图,如图5-4所示。
是
是
否
是
否
是
否
否
图5-4位示图法盘块回收流程图
6.开发环境
Windows系统,运行环境:
VisualC++6.0。
7.结果分析
(1)运行首页面。
(2)输入1,选择位示图法。
(3)选择1,分配文件。
(4)输入文件名1和块数11。
(5)选择1,继续分配文件,并输入文件名2和块数22。
(6)输入1,继续分配文件,并输入文件名3和块数33。
(7)选择2,回收文件,并输入回收文件2。
(8)返回首页面,选择2,用空闲表法。
(9)输入256。
(10)输入1,选择分配,并且输入文件名1和大小11,查看分配状态。
(11)输入1,继续分配,并且输入文件名2和大小22,查看分配状态。
(12)输入2,选择回收,并且输入回收文件名2,查看分配状态。
8.课程设计总结
通过做这个实验,我明白了在做实验前,一定要将课本上的知识吃透,因为这是做实验的基础,否则,在老师讲解时就会听不懂,在编程序时就会思维混乱,摸不清头绪。
做实验时,一定要亲力亲为,务必要将每个步骤,每个细节弄清楚,弄明白。
实验后,还要复习,思考,这样印象才深刻,记得才牢固。
实验的过程中我们必须要弄懂实验的原理。
在这里我深深体会到哲学上理论对实践的指导作用:
弄懂实验原理,而且体会到了实验的操作能力是靠自己亲自动手,亲自开动脑筋,亲自去请教别人才能得到提高的。
在这里,感谢荆老师对我的指导和启迪,感谢同学们对我的帮助,这次实验虽然做的不算特别完美,不过我已经很努力了。
这次实验对我对这部分知识的理解和编程能力有了很大的提高,以后我会更加努力的去做每一件事。
参考文献
【1】汤晓丹、梁红兵·计算机操作系统(第三版)西安:
西安电子科技大学出版社,2007年:
引用231页~233页。
【2】揣锦华·C++程序设计语言(第一版)西安:
西安电子科技大学出版社,2003年。
【3】张坤、姜立秋·操作系统实验教程(第一版)北京:
清华大学出版社,2008年。
附录:
#include
#include
#include
#include
#include
#include
intMAX_SEGMENT=10;//最大碎片值
structPartition//分区表目
{
intPar_Size;//分区大小
intPar_No;//分区序号或者名字
intAddr;//分区地址
intIsUse;//分区使用情况,0表示空闲,1表示使用
Partition*pri;//前向指针
Partition*next;//后向指针
};
Partition*Int()//函数,返回Partition类型指针
{//初始化空闲分区表
Partition*list,*H,*H1;
list=(structPartition*)malloc(sizeof(structPartition));
list->next=NULL;
H=list;
if(!
list)
{
printf("\n错误,初始化分配失败!
程序结束");
exit
(1);
}
H1=(structPartition*)malloc(sizeof(structPartition));
printf("请预先输入分区总大小(以盘块为单位):
");
scanf("%d",&H1->Par_Size);
H1->Addr=0;
H1->Par_No=0;
H1->IsUse=0;
H1->pri=H;
H1->next=NULL;
H->next=H1;////list--->H1
returnlist;
}
Partition*InitFP()
{//初始化已分配分区表
Partition*FP,*F,*H;
inti;
FP=(structPartition*)malloc(sizeof(structPartition));
FP->next=NULL;
H=FP;
for(i=0;i<10;i++)//已分配区先暂定分配十个表目
{
F=(structPartition*)malloc(sizeof(structPartition));
if(!
F)
{
printf("\n错误,分配失败!
程序结束");
exit
(1);
}
F->Par_Size=0;
F->Addr=0;
F->Par_No=0;
F->IsUse=0;
F->next=NULL;
H->next=F;
F->pri=H;
H=H->next;
}
returnFP;
}
Partition*New_Process(Partition*list,Partition*FP)
{//为新的进程分配资源
Partition*H,*P,*H1;
intSize,Name,L;
H=list;
H1=FP->next;
H=H->next;
printf("请输入新文件的名称和大小(整数):
");
scanf("%d%d",&Name,&Size);
while(H)
{
if(!
H)//表目已查完,无法分配
{
printf("\n已无空闲盘区,本次无法分配!
");
returnlist;
}
else{
if(H->IsUse==0)//空表目
//if(H->Par_Size>=Size)//大小满足,空闲分区大小>要分配的大小
if(H->Par_Size>=Size)//大小满足,
{
booltemp=false;
if((H->Par_Size-Size)<=MAX_SEGMENT){//空闲分区大小-要分配的大小<碎片值,会产生碎片,将整个盘块大小分配出去,
Size=H->Par_Size;//分配的大小为整个盘块
temp=true;//会产生碎片
}
//其他情况就分配大小为请求大小,不会产生碎片,
L=H->Addr;//保存空闲分地址
if(temp){
printf("该次分配会产生碎片,将整个盘区大小%d分配出去!
",Size);
}else{
printf("该次分配不会产生碎片");
}
break;
}
}
H=H->next;//否则,继续往下查找
}
if(H)
{
if(H->Par_Size>Size)//大小满足,空闲分区大小》要分配的大小
{
P=(structPartition*)malloc(sizeof(structPartition));//分配新的表目,处理一条数据,分配一次内存
P->IsUse=1;
P->Addr=L;//指向空闲分区地址
P->next=H;//修改指针
H->pri->next=P;
P->pri=H->pri;
H->pri=P;
P->Par_Size=Size;//分配大小为要请求分配的大小
P->Par_No=Name;//名称
H->Par_Size-=Size;//修改空闲分区,H所指区块大小减Size
H->Addr+=Size;//H所指区块地址加Size
}else
{
H->IsUse=1;//大小相等的,把当前表项设置空表目
}
while(H1)
{
if(H1->IsUse==0)
{
H1->Par_No=Name;
H1->Par_Size=Size;
H1->Addr=L;//保存已分配地址
H1->IsUse=1;//在已分配表中设置为已分配
break;
}
H1=H1->next;
}
}else
printf("所申请资源已大过系统所拥有的,请重新输入!
\n");
returnlist;
}
Partition*Reclaim(Partition*list,Partition*FP)
{//结束作业,资源回收,No为作业名,回收内存
Partition*H1,*H2,*H3,*HF;//H1为释放区,H2为后分区,H3为前分区
intNo;//作业名
H1=list;
HF=FP;//可有可无?
H1=H1->next;
HF=FP->next;
printf("请输入您想结束的文件名:
");
scanf("%D",&No);
while(HF)//对已分配表进行操作
{
if(HF->Par_No==No)
{
HF->IsUse=0;//标志为空表目
break;//这时保存着HF所指分区的信息
}
HF=HF->next;
}
if(!
HF)//如果找不到该作业,则提示出错
printf("所输入的文件名称不正确,请重新输入!
");
else{
while(H1)//对空闲表进行操作
{
if(H1->Par_No==No)
{
H1->IsUse=0;//标志为空表目
printf("回收成功");
break;
}
H1=H1->next;
}
H2=H1->next;//后分区
H3=H1->pri;//前分区
if(H2&&H2->IsUse==0)//后接分区为空闲
{
if(H2->next==NULL)//判断后接分区是否为尾结点
{
H1->Par_Size+=H2->Par_Size;//把H2合并到H1
H1->next=NULL;
free(H2);
printf("已回收%d大小盘区",H1->Par_Size);
}else//后分区不为空闲,表示已经被使用
{
H1->Par_Size+=H2->Par_Size;
H1->next=H2->next;
H2->next->pri=H1;
free(H2);
printf("已回收%d大小盘区",H1->Par_Size);
}
}
if(H3&&H3->IsUse==0)//前分区为空闲分区,则合并去前分区
{
H3->Par_Size+=H1->Par_Size;
H3->next=H1->next;
if(H1->next!
=NULL)//若H1为尾结点
H1->next->pri=H3;
free(H1);
printf("已回收%d大小盘区",H1->Par_Size);
}
}
returnlist;
}
voidPrint(Partition*list,Partition*FP)
{//输出已分配分区和空闲分区
Partition*H1,*H2;
H1=list->next;
H2=FP;
H2=H2->next;
printf("****************已分配盘块表*******************\n");
printf("分区序号大小始址状态\n");
while(H2)
{
printf("%d%d%d",H2->Par_No,H2->Par_Size,H2->Addr);
if(H2->IsUse==1)
printf("已分配\n");
else
printf("空表目\n");
H2=H2->next;
}
printf("**************************************************\n");
printf("****************总的空闲盘块表*******************\n");
printf("分区序号大小始址状态\n");
while(H1)
{
printf("%d%d%d",H1->Par_No,H1->Par_Size,H1->Addr);
if(H1->IsUse==1)
printf("已分配\n");
else
printf("空表目\n");
H1=H1->next;
}
printf("**************************************************\n");
}
voidMain_Print(Partition*list,Partition*FP)
{//主入口函数,进行菜单选择
intop;
while
(1)
{
printf("\n主菜单\n");
printf("1.分配\n");
printf("2.回收\n");
printf("3.查看分配状态\n");
printf("4.退出系统\n");
printf("\n请选择:
");
scanf("%d",&op);
switch(op)//根据输入,选择分支方向
{
case1:
New_Process(list,FP);
break;
case2:
Reclaim(list,FP);
break;
case3:
Print(list,FP);
break;
case4:
break;
default:
printf("\n选择错误,请重新选择!
");
break;
}
if(op==4)
break;//退出循环
}
}
/*************************************
下面是位示图方法
*************************************/
intWST[256];
/*************************************
空闲区结构体定义
start_location空闲区对象变量的开始位置
free_number空闲区块数目
next指向下一个空闲区的指针
**************************************/
typedefstructnode{
intstart_location;
intfree_number;
structnode*next;
}free_link;
/*************************************
申请空间作业结构体定义
office[]作业名
begin_location作业申请空间后的开始位置
office_number作业申请空间区的数目
next指向下一个申请空闲区的作业指针
**************************************/
typedefstructlink{
charoffice[20];
intbegin_location;
intoffice_number;
structlink*next;
}office;
/**************************************
相关位示图操作的结构体定义
p空间区链表指针
q作业链表指针
***************************************/
typedefstruct{
free_link*p;
office*q;
}work;
/***************************************
程序菜单
****************************************/
voidmenu(){
printf("文件的存取和回收\n");
printf("1--分配文件\n");
printf("2--回收文件\n");
printf("3--退出\n\t");
printf("请输入选项:
");
}
/***************************************
置空位示图
进行初始化
****************************************/
voidzero_wst(){
inti;
for(i=0;i<256;i++)
WST[i]=0;
}
/****************************************
位示图输出显示
将初始化或者申请或者回收后的位示图进行显示
*****************************************/
voidprint_wst(intWST[256]){
inti,j=0;
printf("%3s","");
for(i=0;i<16;i++)
printf("%3d",i);
printf("\n");
printf("%3d",0);
for(i=0;i<256;i++){
j++;
printf("%3d",WST[i]);
if(j%16==0&&i!
=0&&j!
=256){
printf("\n");
printf("%3d",j/16);
}
}
printf("\n");
}
/**************************************
已经申请空间的作业相关情况输出显示
包括:
作业名
申请空间的开始位置和截至位置
***************************************/
voidprint_office(work*w){
office*q;
q=w->q;
q=q->next;
if(q!
=NULL){
printf("已有文件:
\n");
while(q!
=NULL){
printf("\t%s:
%d-%d\n",q->office,q->begin_location,q->begin_location+q->office_number-1);
q=q->next;
}
}
}
/*************************************
位示图操作的初始化
包括:
空闲区链表的初始化
作业链表的初始化
**************************