操作系统课程设计可变分区存储管理.docx
《操作系统课程设计可变分区存储管理.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计可变分区存储管理.docx(18页珍藏版)》请在冰豆网上搜索。
操作系统课程设计可变分区存储管理
工程技术学院
电气信息系
操作系统课程设计报告
专业:
模拟实现可变分区存储管理
一、设计目的
在熟练掌握计算机分区存储管理方式的原理的基础上,利用C程序设计语言在windows操作系统下模拟实现操作系统的可变分区存储管理的功能,一方面加深对原理的理解,另一方面提高根据已有原理通过编程解决实际问题的能力,为进行系统软件开发和针对实际问题提出高效的软件解决方案打下基础。
二、各功能模块分析实现
1.设计合理的数据结构来描述存储空间:
1)对于未分配出去的部分,用空闲分区链表来描述。
structfreeList
{
intstartAddress;/*分区起始地址*/
intsize;/*分区大小*/
structfreeList*next;/*分区链表指针*/
}
2)对于已经分配出去的部分,由装入内存的作业占据。
structusedList
intjobID;/*分区中存放作业ID*/
structusedList*next;/*分区链表指针*/
3)将作业组织成链表。
structjobList
intid;/*作业ID*/
intsize;/*作业大小(需要的存储空间大小)*/
intstatus;/*作业状态0:
newjob,1:
inthememory,2:
finished.*/
structjobList*next;/*作业链表指针*/
以上将存储空间分为空闲可占用两部分,在usedlist中设jobID而不设size,可以在不增加空间复杂度(与freelist相比)的同时更方便的实现可变分区存储管理(从后面的一些函数的实现上可以得出这个结论)。
尽管设置joblist增加了空间复杂度,但它的存在,使得该程序可以方便的直接利用C盘中的Job.txt文件。
该文件可以认为是一个和其他进程共享的资源。
通过这个文件,其他进程写入数据供读取。
这中思想在操作系统设计中体现的很多。
2.实现分区存储管理的内存分配功能,选择适应算法(首次适应算法,最佳适应算法,最后适应算法,最坏适应算法)。
基本原理分析:
1)Bestfit:
将空闲分区按大小从小到大排序,从头找到大小合适的分区。
2)Worstfit:
将空闲分区按大小从大到小排序,从头找到大小合适的分区。
3)Firstfit:
将空闲分区按起始地址大小从小到大排序,……
4)Lastfit:
将空闲分区按起始地址大小从大到小排序,……
由此,可将空闲分区先做合适的排序后用对应的适应算法给作业分配存储空间。
排序函数order(bySize为零则按分区大小排序,否则按分区起始地址;inc为零从小到大排序,否则从大到小排序;通过empty指针返回结果)。
voidorder(structfreeList**empty,intbySize,intinc)
structfreeList*p,*q,*temp;
intstartAddress,size;
for(p=(*empty)->next;p;p=p->next)
{/*按bySize和inc两个参数寻找合适的节点,用temp指向它*/
for(temp=q=p;q;q=q->next)
switch(bySize)
case0:
switch(inc)
if(q->sizesize)
temp=q;break;
default:
if(q->size>temp->size)
}break;
if(q->startAddressstartAddress)
if(q->startAddress>temp->startAddress)
}/*交换节点的成员值*/
if(temp!
=p)
startAddress=p->startAddress;
size=p->size;
p->startAddress=temp->startAddress;
p->size=temp->size;
temp->startAddress=startAddress;
temp->size=size;
3.实现分区存储管理的内存回收算法:
voidinsertFreeNode(structfreeList**empty,intstartAddress,intsize)
插入回收的空节点分区,处理回收分区与空闲分区的四种邻接关系。
structfreeList*p,*q,*r;
for(p=*empty;p->next;p=p->next);/*处理链表尾部的邻接情况*/
if(p==*empty||p->startAddress+p->size{makeFreeNode(&r,startAddress,size);/*通过r指针返回创建的空闲节点*/r->next=p->next;/*插入独立的空闲节点*/p->next=r;return;}if(p->startAddress+p->size==startAddress)/*与尾部上邻*/{p->size+=size;/*合并尾部节点*/return;}q=(*empty)->next;/*处理链表首节点的邻接情况*/if(startAddress+size==q->startAddress)/*与首节点下邻*/{q->startAddress=startAddress;/*合并首节点*/q->size+=size;}elseif(startAddress+sizestartAddress)/*与首节点不相邻*/{makeFreeNode(&r,startAddress,size);r->next=(*empty)->next;(*empty)->next=r;}else{/*处理链表中间的邻接情况*/while(q->next&&q->startAddress{p=q;q=q->next;}if(p->startAddress+p->size==startAddress&&\q->startAddress==startAddress+size)/*上下邻,合并节点*/{p->size+=size+q->size;p->next=q->next;free(q);/*删除多余节点*/}elseif(p->startAddress+p->size==startAddress&&\q->startAddress!=startAddress+size)/*上邻,增加节点的大小*/{p->size+=size;}elseif(p->startAddress+p->size!=startAddress&&\q->startAddress==startAddress+size)/*下邻*/{q->startAddress=startAddress;/*修改节点起始地址*/q->size+=size;/*修改节点的大小*/}else{/*上下不相邻*/makeFreeNode(&r,startAddress,size);r->next=p->next;p->next=r;}}}4.当碎片产生时,进行碎片的拼接。voidmoveFragment(structjobList*jobs,structfreeList**empty,structusedList**used){intsize,status;structusedList*p;intaddress=memoryStartAddress;/*全局变量,初始化时分配存储空间始址*/if((*empty)->next==NULL)/*空闲分区链表为空,提示并返回*/{printf("\nThememorywasusedoutatall.\nMaybeyoushouldfinishsomejobsfirstorpressanykeytotryagain!");getch();return;}for(p=(*used)->next;p;p=p->next)/*循环的修改占用分区的始址*/{p->startAddress=address;getJobInfo(jobs,p->jobID,&size,&status);/*由作业ID获得作业大小*/address+=size;}(*empty)->next->startAddress=address;/*修改空闲分区的首节点始址、大小*/(*empty)->next->size=memorySize-(address-memoryStartAddress);(*empty)->next->next=NULL;/*删除首节点后的所有节点*/}5.空闲分区队列显示:intshowFreeList(structfreeList*empty)6.作业占用链表显示:intshowUsedList(structjobList*jobs,structusedList*used)从头到尾显示used链,同时通过其中的作业ID在jobs中查对应的大小。7.从键盘输入作业到D盘的JOB文件:voidinputJob(void)8.从JOB文件中读出作业并创建作业链表:intmakeJobList(structjobList**jobs)9.显示作业链表:intshowJobList(structjobList*jobs)10.更新作业链表中作业的状态:intupdateJobFile(structjobList*jobs)11.根据作业链表更新JOB文件:intupdateJobFile(structjobList*jobs)12.为作业分配存储空间、状态必须为0:intallocate(structfreeList**empty,intsize)13.结束一个作业号为id的作业,释放存储空间(由*startAddress返回空间的起始地址):intfinishJob(structusedList**used,intid,int*startAddress)14.插入释放的空间到used链表中(作业号为id,startAddress由函数13返回):voidinsertUsedNode(structusedList**used,intid,intstartAddress)15.获取作业的信息:voidgetJobInfo(structjobList*jobs,intid,int*size,int*status)16.初始化存储空间起始地址、大小:voidiniMemory(void)17.选择适应算法:charselectFitMethod(void)18.根据参数startAddress、size创建空闲节点,由empty指针返回:voidmakeFreeNode(structfreeList**empty,intstartAddress,intsize)19.以要求的方式打开文件:voidopenFile(FILE**fp,char*filename,char*mode)20.出现严重错误时显示信息并结束程序;voiderrorMessage(void)三、总体界面与程序流程分析DynamicZonalMemoryManagement其中1、Initializiation.按顺序利用了openFile()、iniMemory()、makeFreeNode()、inputJob()(选择利用C盘JOB文件时提供作业信息)、makeJobList()、allocate()、insertUsedNode()(选择利用C盘JOB文件时先将状态为1的作业放到存储空间中,以恢复上次的模拟实验,或使本次模拟时不出错)selectFitMethod()等自编函数。2、Putjobintomemory(allocatememory)按顺序利用了showJobList()(选手动逐个为作业分配存储空间时)、openFile()、order()、allocate()、errorMessage()、insertUsedNode()、updateJobStatus()updateJobFile()函数(自动为如上作业分配存储后状态的变化——>)3、Finishjob(reusememory)按顺序利用了openFile()、showUsedList()、getJobInfo()、insertFreeNode()、updateJobStatus()、updateJobFile()、errorMessage()等自编函数。(完成部分作业后作业——>)4、Showcurrentfreelist按顺序利用了openFile()、showFreeList()函数。(如下图为当前空闲分区)5、Showcurrentmemoryusedbyjobs按顺序利用了openFile()、showUsedList()函数。(如下图为当前作业占用的分区)6、Movefragmenttogether按顺序利用了openFile()、moveFragment()函数。整理7、Exit按顺序利用了openFile()、exit(0)函数。四、主程序流程图step=’1’step=’2’step=’6’step=’3’step=’4’step=’5’step=’7’五、结果分析与总结程序中创建的两个文件1)Bestfit算法验证:如下图分配大小为50的8号作业,恰好占用大小为50的空闲而非大小为240的。2)Worstfit算法验证:如下图分配大小为50的8号作业,占用大小为100空闲而非大小为70的。3)Firstfit算法验证:如下图分配大小为50的8号作业,占用起始地址为110空闲而非350的。4)Lastfit算法验证:如下图分配大小为50的8号作业,占用起始地址为350空闲而非110的。总结:通过这次课程设计我练习了用C语言写系统软件,对OS中可变分区存储管理有了更深刻的了解。在写程序的时候也遇到了一些困难。比如在设计数据结构时特别犹豫,总想找一个很合适的。但是,后来才知道,关键要多尝试,而空想是没有用的。最后我证实了自己的设计的合理性。还有为了使程序更健壮,我尝试着将程序中的输入部分全部改为字符(串)。成功的避免了接受整型数据时输入字符后引起的错误,使程序能接受任何输入而正常结束。很遗憾的是因为时间问题,没有把这个模拟程序写成动画形式,还可以加几句代码后实现动态的增加作业。
makeFreeNode(&r,startAddress,size);/*通过r指针返回创建的空闲节点*/
r->next=p->next;/*插入独立的空闲节点*/
p->next=r;
return;
if(p->startAddress+p->size==startAddress)/*与尾部上邻*/
p->size+=size;/*合并尾部节点*/
q=(*empty)->next;/*处理链表首节点的邻接情况*/
if(startAddress+size==q->startAddress)/*与首节点下邻*/
q->startAddress=startAddress;/*合并首节点*/
q->size+=size;
elseif(startAddress+sizestartAddress)/*与首节点不相邻*/
makeFreeNode(&r,startAddress,size);
r->next=(*empty)->next;
(*empty)->next=r;
else
{/*处理链表中间的邻接情况*/
while(q->next&&q->startAddress{p=q;q=q->next;}if(p->startAddress+p->size==startAddress&&\q->startAddress==startAddress+size)/*上下邻,合并节点*/{p->size+=size+q->size;p->next=q->next;free(q);/*删除多余节点*/}elseif(p->startAddress+p->size==startAddress&&\q->startAddress!=startAddress+size)/*上邻,增加节点的大小*/{p->size+=size;}elseif(p->startAddress+p->size!=startAddress&&\q->startAddress==startAddress+size)/*下邻*/{q->startAddress=startAddress;/*修改节点起始地址*/q->size+=size;/*修改节点的大小*/}else{/*上下不相邻*/makeFreeNode(&r,startAddress,size);r->next=p->next;p->next=r;}}}4.当碎片产生时,进行碎片的拼接。voidmoveFragment(structjobList*jobs,structfreeList**empty,structusedList**used){intsize,status;structusedList*p;intaddress=memoryStartAddress;/*全局变量,初始化时分配存储空间始址*/if((*empty)->next==NULL)/*空闲分区链表为空,提示并返回*/{printf("\nThememorywasusedoutatall.\nMaybeyoushouldfinishsomejobsfirstorpressanykeytotryagain!");getch();return;}for(p=(*used)->next;p;p=p->next)/*循环的修改占用分区的始址*/{p->startAddress=address;getJobInfo(jobs,p->jobID,&size,&status);/*由作业ID获得作业大小*/address+=size;}(*empty)->next->startAddress=address;/*修改空闲分区的首节点始址、大小*/(*empty)->next->size=memorySize-(address-memoryStartAddress);(*empty)->next->next=NULL;/*删除首节点后的所有节点*/}5.空闲分区队列显示:intshowFreeList(structfreeList*empty)6.作业占用链表显示:intshowUsedList(structjobList*jobs,structusedList*used)从头到尾显示used链,同时通过其中的作业ID在jobs中查对应的大小。7.从键盘输入作业到D盘的JOB文件:voidinputJob(void)8.从JOB文件中读出作业并创建作业链表:intmakeJobList(structjobList**jobs)9.显示作业链表:intshowJobList(structjobList*jobs)10.更新作业链表中作业的状态:intupdateJobFile(structjobList*jobs)11.根据作业链表更新JOB文件:intupdateJobFile(structjobList*jobs)12.为作业分配存储空间、状态必须为0:intallocate(structfreeList**empty,intsize)13.结束一个作业号为id的作业,释放存储空间(由*startAddress返回空间的起始地址):intfinishJob(structusedList**used,intid,int*startAddress)14.插入释放的空间到used链表中(作业号为id,startAddress由函数13返回):voidinsertUsedNode(structusedList**used,intid,intstartAddress)15.获取作业的信息:voidgetJobInfo(structjobList*jobs,intid,int*size,int*status)16.初始化存储空间起始地址、大小:voidiniMemory(void)17.选择适应算法:charselectFitMethod(void)18.根据参数startAddress、size创建空闲节点,由empty指针返回:voidmakeFreeNode(structfreeList**empty,intstartAddress,intsize)19.以要求的方式打开文件:voidopenFile(FILE**fp,char*filename,char*mode)20.出现严重错误时显示信息并结束程序;voiderrorMessage(void)三、总体界面与程序流程分析DynamicZonalMemoryManagement其中1、Initializiation.按顺序利用了openFile()、iniMemory()、makeFreeNode()、inputJob()(选择利用C盘JOB文件时提供作业信息)、makeJobList()、allocate()、insertUsedNode()(选择利用C盘JOB文件时先将状态为1的作业放到存储空间中,以恢复上次的模拟实验,或使本次模拟时不出错)selectFitMethod()等自编函数。2、Putjobintomemory(allocatememory)按顺序利用了showJobList()(选手动逐个为作业分配存储空间时)、openFile()、order()、allocate()、errorMessage()、insertUsedNode()、updateJobStatus()updateJobFile()函数(自动为如上作业分配存储后状态的变化——>)3、Finishjob(reusememory)按顺序利用了openFile()、showUsedList()、getJobInfo()、insertFreeNode()、updateJobStatus()、updateJobFile()、errorMessage()等自编函数。(完成部分作业后作业——>)4、Showcurrentfreelist按顺序利用了openFile()、showFreeList()函数。(如下图为当前空闲分区)5、Showcurrentmemoryusedbyjobs按顺序利用了openFile()、showUsedList()函数。(如下图为当前作业占用的分区)6、Movefragmenttogether按顺序利用了openFile()、moveFragment()函数。整理7、Exit按顺序利用了openFile()、exit(0)函数。四、主程序流程图step=’1’step=’2’step=’6’step=’3’step=’4’step=’5’step=’7’五、结果分析与总结程序中创建的两个文件1)Bestfit算法验证:如下图分配大小为50的8号作业,恰好占用大小为50的空闲而非大小为240的。2)Worstfit算法验证:如下图分配大小为50的8号作业,占用大小为100空闲而非大小为70的。3)Firstfit算法验证:如下图分配大小为50的8号作业,占用起始地址为110空闲而非350的。4)Lastfit算法验证:如下图分配大小为50的8号作业,占用起始地址为350空闲而非110的。总结:通过这次课程设计我练习了用C语言写系统软件,对OS中可变分区存储管理有了更深刻的了解。在写程序的时候也遇到了一些困难。比如在设计数据结构时特别犹豫,总想找一个很合适的。但是,后来才知道,关键要多尝试,而空想是没有用的。最后我证实了自己的设计的合理性。还有为了使程序更健壮,我尝试着将程序中的输入部分全部改为字符(串)。成功的避免了接受整型数据时输入字符后引起的错误,使程序能接受任何输入而正常结束。很遗憾的是因为时间问题,没有把这个模拟程序写成动画形式,还可以加几句代码后实现动态的增加作业。
p=q;
q=q->next;
if(p->startAddress+p->size==startAddress&&\
q->startAddress==startAddress+size)/*上下邻,合并节点*/
p->size+=size+q->size;
p->next=q->next;
free(q);/*删除多余节点*/
elseif(p->startAddress+p->size==startAddress&&\
q->startAddress!
=startAddress+size)/*上邻,增加节点的大小*/
p->size+=size;
elseif(p->startAddress+p->size!
=startAddress&&\
q->startAddress==startAddress+size)/*下邻*/
q->startAddress=startAddress;/*修改节点起始地址*/
q->size+=size;/*修改节点的大小*/
{/*上下不相邻*/
r->next=p->next;
4.当碎片产生时,进行碎片的拼接。
voidmoveFragment(structjobList*jobs,structfreeList**empty,structusedList**used)
intsize,status;
structusedList*p;
intaddress=memoryStartAddress;/*全局变量,初始化时分配存储空间始址*/
if((*empty)->next==NULL)/*空闲分区链表为空,提示并返回*/
printf("\nThememorywasusedoutatall.\nMaybeyoushouldfinishsomejobsfirstorpressanykeytotryagain!
");
getch();
for(p=(*used)->next;p;p=p->next)/*循环的修改占用分区的始址*/
p->startAddress=address;
getJobInfo(jobs,p->jobID,&size,&status);/*由作业ID获得作业大小*/
address+=size;
(*empty)->next->startAddress=address;/*修改空闲分区的首节点始址、大小*/
(*empty)->next->size=memorySize-(address-memoryStartAddress);
(*empty)->next->next=NULL;/*删除首节点后的所有节点*/
5.空闲分区队列显示:
intshowFreeList(structfreeList*empty)
6.作业占用链表显示:
intshowUsedList(structjobList*jobs,structusedList*used)
从头到尾显示used链,同时通过其中的作业ID在jobs中查对应的大小。
7.从键盘输入作业到D盘的JOB文件:
voidinputJob(void)
8.从JOB文件中读出作业并创建作业链表:
intmakeJobList(structjobList**jobs)
9.显示作业链表:
intshowJobList(structjobList*jobs)
10.更新作业链表中作业的状态:
intupdateJobFile(structjobList*jobs)
11.根据作业链表更新JOB文件:
12.为作业分配存储空间、状态必须为0:
intallocate(structfreeList**empty,intsize)
13.结束一个作业号为id的作业,释放存储空间(由*startAddress返回空间的起始地址):
intfinishJob(structusedList**used,intid,int*startAddress)
14.插入释放的空间到used链表中(作业号为id,startAddress由函数13返回):
voidinsertUsedNode(structusedList**used,intid,intstartAddress)
15.获取作业的信息:
voidgetJobInfo(structjobList*jobs,intid,int*size,int*status)
16.初始化存储空间起始地址、大小:
voidiniMemory(void)
17.选择适应算法:
charselectFitMethod(void)
18.根据参数startAddress、size创建空闲节点,由empty指针返回:
voidmakeFreeNode(structfreeList**empty,intstartAddress,intsize)
19.以要求的方式打开文件:
voidopenFile(FILE**fp,char*filename,char*mode)
20.出现严重错误时显示信息并结束程序;voiderrorMessage(void)
三、总体界面与程序流程分析
DynamicZonalMemoryManagement
其中1、Initializiation.按顺序利用了openFile()、iniMemory()、makeFreeNode()、inputJob()(选择利用C盘JOB文件时提供作业信息)、makeJobList()、allocate()、insertUsedNode()(选择利用C盘JOB文件时先将状态为1的作业放到存储空间中,以恢复上次的模拟实验,或使本次模拟时不出错)selectFitMethod()等自编函数。
2、Putjobintomemory(allocatememory)
按顺序利用了showJobList()(选手动逐个为作业分配存储空间时)、openFile()、order()、allocate()、errorMessage()、insertUsedNode()、updateJobStatus()updateJobFile()函数
(自动为如上作业分配存储后状态的变化——>)
3、Finishjob(reusememory)
按顺序利用了openFile()、showUsedList()、getJobInfo()、insertFreeNode()、updateJobStatus()、updateJobFile()、errorMessage()等自编函数。
(完成部分作业后作业——>)
4、Showcurrentfreelist按顺序利用了openFile()、showFreeList()函数。
(如下图为当前空闲分区)
5、Showcurrentmemoryusedbyjobs按顺序利用了openFile()、showUsedList()函数。
(如下图为当前作业占用的分区)
6、Movefragmenttogether按顺序利用了openFile()、moveFragment()函数。
整理
7、Exit按顺序利用了openFile()、exit(0)函数。
四、主程序流程图
step=’1’
step=’2’
step=’6’
step=’3’step=’4’
step=’5’
step=’7’
五、结果分析与总结
程序中创建的两个文件
1)Bestfit算法验证:
如下图分配大小为50的8号作业,恰好占用大小为50的空闲而非大小为240的。
2)Worstfit算法验证:
如下图分配大小为50的8号作业,占用大小为100空闲而非大小为70的。
3)Firstfit算法验证:
如下图分配大小为50的8号作业,占用起始地址为110空闲而非350的。
4)Lastfit算法验证:
如下图分配大小为50的8号作业,占用起始地址为350空闲而非110的。
总结:
通过这次课程设计我练习了用C语言写系统软件,对OS中可变分区存储管理有了更深刻的了解。
在写程序的时候也遇到了一些困难。
比如在设计数据结构时特别犹豫,总想找一个很合适的。
但是,后来才知道,关键要多尝试,而空想是没有用的。
最后我证实了自己的设计的合理性。
还有为了使程序更健壮,我尝试着将程序中的输入部分全部改为字符(串)。
成功的避免了接受整型数据时输入字符后引起的错误,使程序能接受
任何输入而正常结束。
很遗憾的是因为时间问题,没有把这个模拟程序写成动画形式,还可以加几句代码后实现动态的增加作业。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1