操作系统一个小型操作系统地设计与实现课程设计文档格式.docx
- 文档编号:19072852
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:42
- 大小:284.93KB
操作系统一个小型操作系统地设计与实现课程设计文档格式.docx
《操作系统一个小型操作系统地设计与实现课程设计文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统一个小型操作系统地设计与实现课程设计文档格式.docx(42页珍藏版)》请在冰豆网上搜索。
1)首次适应法
分配流程图
返回分配给进程的内存首地址
首次适应算法回收流程图
将p放在链首,
并修改其状态位为空闲
2)最佳适应法
将合并的或释放的分区按长度升序重新插入到自由链表中。
回收内存流程
C.虚拟存储器的缺页调度
1)先进先出FIFO
开始FIFO的缺页中断处理
查主存分块表
有空闲块可用?
分配一块
J=p[HEAD]
J的修改标志=1?
输出“将J页复写入交换区”
输出“装入L页”
调整FIFO队列,将L插入队尾(HEAD=(HEAD+1)modM)
修改主存分块表和页表
终止
FIFO淘汰算法流程
2)LRU
开始LRU的缺页中断处理
找到栈底元素:
J=p[M-1]
输出“将J页送到入交换区”
调整堆栈,使HEAD所指元素及以下的元素下移P[HEAD]=L
LRU淘汰算法流程
实现原理
主界面
设计一个框架分别去链接处理机管理、存储器管理和缺页调度相关的程序。
(1)任务
先来先服务的调度算法实现处理机调度。
(2)要求
1.实现对FCFS算法的模拟实现
2.计算出该算法的平均作业周转时间、平均带权作业周转时间。
(3)原理
按作业到达CPU时间先后顺序进行非剥夺式调度,先到达CPU的作业先被执行。
(4)数据结构
structtask_struct
{
charname;
/*进程名称*/
intnumber;
/*进程编号*/
floatcome_time;
/*到达时间*/
floatrun_begin_time;
/*开始运行时间*/
floatrun_time;
/*运行时间*/
floatrun_end_time;
/*运行结束时间*/
intpriority;
/*优先级*/
intorder;
/*运行次序*/
intrun_flag;
/*调度标志*/
}tasks[MAX];
intfcfs()/*先来先服务算法*/
进程名
链接指针
到达时间
估计运行时间
进程状态
进程控制块结构
(5)实现方法
建立一个链表按照到达CPU的时间从小到大排列,只需从第一个作业(头结点)依次调度到最后一个作业(尾结点)。
(6)运行界面
测试数据:
作业名
运行时间
A
28
B
9
C
3
执行FCFS算法如下:
2)时间片轮转法
只对进程的运行模拟,将其运行时间加一,判断要求运行时间与已运行时间是否相等,若相等则表示进程结束,进程退出调度,释放资源。
1.实现对RR算法的模拟实现
2.显示执行完一个时间片的结果。
时间片轮转算法中,系统将所有的就程序按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。
当执行的时间片用完时,调度程序停止该进程的执行,并将它送往就绪队列的末尾;
然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。
temp->
state='
R'
;
//初始状态每个进程均为运行态
allocation=0;
//初始时进程均不占用cpu
num+=temp->
need_time;
//用num来限制循环的次数
处理器调度总是选择标志单元指示的进程运行。
执行:
已运行时间+1
来模拟进程的一次运行,表示进程已经运行过一个单位的时间。
当一个进程被选中运行时,必须设置该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片
进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。
同时,应判断该进程的要求运行时间与已运行时间,若该进程的要求运行时间已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。
若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应指导它的状态修改成“结束”且退出队列。
此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置。
作业号
执行时间/s
1
2
执行时间片轮转算法RR如下:
通过采用首次适应算法实现内存的分配与回收,并可以查看和显示当前内存现状。
1.实现对FF算法的模拟实现
2.输入要进行分配内存的进程ID和相应所需内存大小,回收内存时输入已运行的进程ID。
FF算法要求空闲链已地址递增的次序连接。
分配内存时,从链首开始顺序查找,直到找到第一个满足要求的空间并分配给进程,把分配后余下的空间仍然留在链表中。
若从链首至链尾都不满足要求,则分配失败。
该算法倾向于优先使用低地址的空间。
intconstMEMO=256;
//初始化常类型MEMO,用MEMO表示内存大小(常类型的变量或对象的值是不能被更新的)
structFreeMemory
{
intID;
intStartAdd;
intSize;
boolState;
//定义state为布尔型变量,其值只有真(TRUE)和假(FALSE)
FreeMemory*Next;
};
FreeMemory*AllocTable=newFreeMemory;
//建立全局管理表用于内与回收
FreeMemory*PtrforCycleFit=AllocTable;
//为循环首次适应定义的指针,此指针用于指向当前查找的起始地址;
//初始化内存函数
voidMemoryInit(FreeMemory*&
tempAdd)
tempAdd->
ID=0;
//初始化当前进程为空
Size=MEMO;
//初始化可分配空间为内存大小
StartAdd=0;
//初始化起始地址为0
State=false;
//初始化状态为未分配
Next=NULL;
//初始化下一个进程也为空
}
//反馈内存现态
voidDispMemory()
FreeMemory*temp=AllocTable;
//全局管理表反映内存状态
cout<
<
"
系统总内存:
"
MEMO<
endl;
for(;
temp;
temp=temp->
Next)
进程ID:
temp->
ID<
大小:
Size<
起始地址:
StartAdd<
是否已分配:
State<
}//输出内存的各个变量
可变式分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区的个数是可以调整的。
当需要装入一个作业时,根据作业需要的贮存量,查看是否有足够的空闲空间,若有,则按需求量分割一部分给作业;
若无,则作业等待。
随着作业的装入、完成,主存空间被分割成许多大大小小的分区。
有的分区被分配作业占用,有的分区空闲。
在空闲区表中,按空闲区首地址从低到高进行登记。
当一个作业执行完成时,作业所占用的分区应归还给系统。
在归还时,要考虑相邻空间区合并问题。
作业的释放区与空闲区的邻接分以下4种情况考虑:
A、释放区下邻空闲区;
B、释放区上邻空闲区;
C、释放区上下都与空闲区邻接;
D、释放区上邻空闲区不邻接。
系统总内存为256时,分别为进程1、2、3分配大小为64、128、64的内存。
执行首次适应算法分配内存如下:
若回收进程2的内存,执行结果如下:
2)最佳适应法
通过采用最佳适应算法实现内存的分配与回收,并可以查看和显示当前内存现状。
1.实现对BF算法的模拟实现
2.输入要进行分配内存的进程ID和相应所需内存大小,回收内存时输入需要回收的内存块。
最佳适应算法扫描整个未分配表或链表,从空闲区中挑选一个能满足用户进程要求的最小分区进行分配。
此算法保证不会分割一个更大的区域,使得装入大作业的要求容易得到满足,同时,通常把空闲区按长度递增顺序排列,查找时总是从最小的一个空闲区开始,直至找到满足要求的分区为止,这时,最佳适应分配算法等同于首次适应算法。
此算法的主存利用率好,所找出的分区如果最好满足要求则是最合适的。
boolAlloc_BestFit(intid,intTrySize)
{//查找满足此条件的x1<
=TrySize<
=x2的分区,然后将其放置在x2中,并将x2拆分成两个分区
SortPartition(true);
//使用快速排序算法,升序排序
for(;
/*回收操作,回收过程中,要用到三个指针,上一个Last,当前temp,下一个temp->
next
当temp指向表头或表尾时需要特殊考虑*/
//当要退出工作时,就要回收//此退出的工作由执行函数调用
voidEndJob(intid)
Free_Memory(id);
空闲区设置为双向链表,其双向链的分区格式为:
0(状态位)
分区大小(N+2)
向前指针
大小为N的已分配区或空闲区
向后指针
测试数据如下:
进程
4
5
6
所需内存
25
34
45
12
13
10
执行最佳适应算法为其分配内存如下:
若回收进程4,执行结果如下:
采用先进先出FIFO算法实现分页管理的缺页调度,并输出每次调入调出的页号和运行结果。
1.实现对FIFO算法的模拟实现
2.输出每次执行的结果。
基于程序总是按线性顺序来访问物理空间这一假设,总是淘汰最先调入主存的页面,即淘汰在主存中驻留时间最长的页面,认为驻留时间最长的页不再使用的可能性较大。
voidFIFO(){
intlength;
intfifo[100]={0};
intpageLength;
intfifoPage[100]={0};
inti,j;
***********************先进先出算法**************************"
pageLength=3;
length=9;
for(i=1;
i<
=length;
i++){
intflag=0;
for(j=1;
j<
=pageLength;
j++){
if(fifo[i]==fifoPage[j]){
flag=1;
j=pageLength+1;
}elseif(fifoPage[j]==0){
fifoPage[j]=fifo[i];
}
}
if(flag==1)
{
else
cout<
→淘汰"
fifoPage[1]<
for(j=1;
fifoPage[j]=fifoPage[j+1];
fifoPage[pageLength]=fifo[i];
当采用先进先出算法时,用一个数组构成先进先出队列,数组中各个元素为进程已在主存的页号,其队列头指针初始化为0.假设分配给每个进程的内存块数固定。
当队列满需淘汰时,淘汰最先进入主存的一页。
若该页修改过,还有存入磁盘。
然后要把当前访问的页装入该块,并修改页表和存储分块表的对应标志。
页表长度:
9;
页框长度:
3;
页面请求数列:
4,4,3,5,1,1,2,3,2
执行先进先出FIFO算法结果如下:
2)LRU
采用先进先出LRU算法实现分页管理的缺页调度,并输出每次调入调出的页号和运行结果。
1.实现对LRU算法的模拟实现
最近最少使用页面替换算法淘汰的页面是在最近一段时间内最久未被访问的那一页,它是基于程序局部性原理来考虑的,认为那些刚被使用过的页面可能还有立即被使用,而那些在较长时间内未被使用的页面可能不会立即使用。
在分页虚拟存储系统中,当硬件发出缺页中断后转操作系统处理缺页中断。
如果主存中已无空闲块,可采用LRU算法进行缺页处理。
voidLRU()
intlru[100]={0};
intlruPage[100]={0};
***********************最近最少使用LRU算法***********************"
if(lru[i]==lruPage[j]){
for(intcc=j;
cc>
0;
cc--){
lruPage[cc]=lruPage[cc-1];
}
lruPage[1]=lru[i];
}elseif(lruPage[j]==0){
for(intvv=j;
vv>
vv--){
lruPage[vv]=lruPage[vv-1];
lruPage[pageLength]<
for(j=pageLength;
j>
j--){
lruPage[j]=lruPage[j-1];
lruPage[1]=lru[i];
当采用LRU算法时,用一个数组构成堆栈,堆栈中各个元素为进程已在主存的页号,为了进行页面置换,可设置一个栈指针,初始化为0.假定分配给每个进程的内存块数固定不变。
当队列满需淘汰时,操作系统选择栈底元素淘汰,其他元素向下移一个位置,将新调入页放栈指针指示的栈顶。
当访问的页在栈中时,还应调整页从当前位置到栈顶。
2,3,5,1,5,5,4,4,3
执行最近最少使用LRU算法结果如下:
总结与体会
通过本次课程设计让我对于图形界面设计有了一定的思路和看法,同时我对先来先服务、时间片轮转、首次适应算法、最佳适应算法、先进先出和最近最少使用算法有了更详尽的认识。
在编程的过程中发现会用到大量的指针,用指针来操作大量的数据比较方便,但最后应该记得释放资源。
从这次实验中我发现我对于c++掌握也有所不足,程序经过了多次修改才得以完善,在以后应该注重编程方面的训练。
此外我还更深入的理解了各个进程调度算法,及实现过程。
在编写程序时查询了很多资料,间接提高了我的搜索能力。
在此次课程设计过程中,对进程的相关知识有了一定的加深。
特别是对进程的进程控制块的存在和价值有了更进一步的认识。
在编写程序的过程之中,对进程自身信息的设计和管理以及调度的算法都有助于对书本知识的理解和掌握。
特别是设计先来先服务调度算法和时间片轮转调度算法的时候,对进程的调度算法有了更好的深入理解。
对进程管理中的等待队列,就绪队列,时间片等概念有了更深刻的印象。
在设计此模拟操作系统的课设中,也加深了对c++知识的把握。
解决了一些以往在编程中遇到了困难。
通过此次的课程设计,不仅提高了对操作系统的认知,也在同时提高了编程的能力,加强了实践。
另外,我觉得此次课程设计虽然主要问题是在编程上,但是经过不断的去调试,还是成功的调试了出来。
但是这几个程序用了多天的时间进行分析和修改,虽然出现了不少问题,但收获颇多!
源代码:
#include<
iostream>
cstring>
#include<
cstddef>
usingnamespacestd;
intfcfsoutput();
/*调度结果输出*/
intfcfsinput();
//进程参数的初始化
voidkaishi();
#defineMAX10
structnode//建立链表来存放进程数据
charname[5];
//进程名称
intneed_time;
//所需要的时间
intallocation;
//占用cpu的情况
charstate;
//目前的状态R为运行,E为运行完毕
node*next;
//链表的尾结点
structtask_struct
/*调度标志*/
intcounter;
/*实际进程个数*/
fcfsinput();
floattime_temp=0;
inti;
intnumber_schedul;
time_temp=tasks[0].come_time;
for(i=0;
counter;
i++)
tasks[i].run_begin_time=time_temp;
tasks[i].run_end_time=tasks[i].run_begin_time+tasks[i].run_time;
tasks[i].run_flag=1;
time_temp=tasks[i].run_end_time;
number_schedul=i;
tasks[number_schedul].order=i+1;
fcfsoutput();
return0;
intfcfsinput()
{
task_structtt;
//初始化进程数
counter=3;
//初始化每个到达系统的时间为5、7、8
tasks[0].come_time=rand()%9;
tasks[1].come_time=rand()%9;
tasks[2].come_time=rand()%9;
3;
for(j=0;
3-i;
j++)
if(tasks[j].come_time>
tasks[j+1].come_time)
{
tt=tasks[j];
tasks[j]=tasks[j+1];
tasks[j+1]=tt;
}
}
//初始化每个进程估计运行的时间
tasks[0].run_time=28;
tasks[1].run_time=9;
tasks[2].run_time=3;
//初始化每个进程的名字
tasks[0].name='
A'
tasks[1].name='
B'
tasks[2].name='
C'
************************先来先服务算法************************"
endl<
tasks[i].run_begin_time=0;
tasks[i].run_end_time=0;
tasks[i].order=0;
tasks[i].run_flag=0;
intfcfsoutput()/*调度结果输出*/
floatturn_round_time=0,f1,w=0;
cout<
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 一个 小型 设计 实现 课程设计