学士学位论文基于c语言的小型模拟操作系统设计.docx
《学士学位论文基于c语言的小型模拟操作系统设计.docx》由会员分享,可在线阅读,更多相关《学士学位论文基于c语言的小型模拟操作系统设计.docx(41页珍藏版)》请在冰点文库上搜索。
学士学位论文基于c语言的小型模拟操作系统设计
本科生毕业设计(创作)
题 目基于C语言的小型模拟操作系统设计
(只包含进程管理和存储管理)
姓 名
学 号
院 系 计算机系
专 业 计算机科学与技术
指导教师
2013年6月
教务处制
本科生毕业设计(论文、创作)声明
本人郑重声明:
所呈交的毕业设计,是本人在指导教师指导下,进行研究工作所取得的成果。
除文中已经注明引用的内容外,本设计的研究成果不包含任何他人创作的、已公开发表或没有公开发表的作品内容。
对本论文所涉及的研究工作做出贡献的其他个人和集体,均已在文中以明确方式标明。
本设计创作声明的法律责任由本人承担。
作者签名:
年月日
本人声明:
该毕业设计是本人指导学生完成的研究成果,已经审阅过毕业设计的全部内容,保证题目、关键词、摘要部分中英文内容的一致性和准确性,并通过一定检测手段保证毕业设计未发现违背学术道德诚信的不端行为。
指导教师签名:
年月日
基于C语言的小型模拟操作系统设计
(只包含进程管理和存储管理)
摘要
本设计采用VisualC++开发工具在Windows环境下设计一个模拟操作系统。
根据操作系统理论知识的学习实现了进程管理和存储管理。
进程管理部分主要实现了进程的创建和撤销、进程的运行。
进程的创建和撤销主要应用指针和链表的知识,进程的运行方式采用的是时间片轮转调度算法,通过输入相关指令可以看到多个进程在时间片调度算法下由就绪态到运行态再到完成态的全过程。
存储管理部分主要实现了进程内存空间的分配和回收。
存储分配采用基本分页存储管理方式,通过数组来模拟主存空间。
创建进程的同时完成对用户提出内存块数的分配,并显示在屏幕上。
内存回收模块的作用是将处于指针队列的控制块移出队列并释放进程所占用的内存。
本人在设计此系统过程中做了如下工作:
(1)仔细阅读了操作系统的进程管理和存储器管理部分的内容,并详细分析了其中的原理。
(2)学习了C语言中的数组、指针等相关知识,并对相关算法做了仔细的阅读和分析。
(3)熟悉了软件工程开发的基本方法、模型、步骤等,确定了系统的框架。
(4)使用C语言编写了模拟操作系统。
通过这次模拟操作系统的设计,加深了自己对操作系统实现思路的理解,直观的理解了操作系统的相关原理,提高了自己编写程序和调试程序的能力,为以后的进一步学习提供了一个良好的开端。
关键词:
操作系统,进程管理,存储管理,分页,时间片
SmallsimulationoperatingsystemdesignbasedonClanguage
(onlyincludesprocessmanagementandstoragemanagement)
Abstract
ThisdesignusestheVisualC++developmenttoolsinWindowsenvironmentdesignasimulationoperatingsystem.Accordingtotheoperatingsystemtostudythetheoryknowledgetorealizetheprocessmanagementandstoragemanagement.Processmanagementpartismainlytoachievetheprocessofcreationandcancellation,theoperationoftheprocess.Processcreationandrevokethemainapplicationofpointerandlinkedlist,processtheoperationmodeofusingthetimeslicerotationschedulingalgorithm,throughinputthecommandcanseemultipleprocessesunderthetimesliceschedulingalgorithmbythereadystatetoarunningstateandthentofinishthewholecourseofstate.Storagemanagementpartmainlyrealizestheprocessmemoryspaceallocationandrecycling.Storageallocationusingbasicpagestoragemanagementmode,throughthearraytosimulatethemainmemoryspace.
Inthedesignofthesystemintheprocessofdoingthefollowingwork:
1,readtheprocessmanagementandstoragemanagementcomponentoftheoperatingsystem,andanalyzesindetailtheprincipleof2,tolearntherelevantknowledgesuchasarrays,PointersinClanguage,andmadeacarefulreadingandanalysisofrelevantalgorithm.3,familiarwiththebasicmethodofthesoftwareengineeringdevelopment,models,procedures,etc.,determinetheframeworkofthesystem.4,usingClanguagetowritethesimulationoperatingsystem.
Bydesigningsimulationoperatingsystem,deepentheirunderstandingofoperatingsystemimplementationapproach,intuitiveunderstandingoftherelevantprincipleoftheoperatingsystem,itimprovestheabilityofwritingyourownprogramanddebugging,forfuturefurtherstudyprovidesagoodplacetostart.
KeyWords:
Operatingsystem,processmanagement,memorymanagement,paging,timeslice
1绪论
1.1背景
操作系统(OS,OperatingSystem)是计算机系统的核心和灵魂,是计算机系统必不可少的组成部分,任何其他软件都必须在操作系统的支持下才能运行。
操作系统的功能强大、代码量大,阅读理解实际系统对于一般的学习者来说几乎是不可能的,因此为了更好地理解操作系统的运行机制,根据操作系统的原理和实际系统的组织结构和一些具体实现,设计一个模拟的操作系统来帮助我们更好地掌握操作系统的原理是非常必要的。
1.2设计目标
在多道程运行环境下,用户可以通过模拟操作系统的交互界面创建进程并按照基本分页存储管理方式分配必要的内存空间,按照时间片轮转算法选择一个或几个进程在处理机上运行。
当程序执行完毕时,系统可以撤销进程并收回它所占用的内存空间。
模拟操作系统不涉及具体的硬件,通过设计合理的数据结构来表示硬件资源,并通过输出一些提示信息表示系统当前的运行状态。
通过设计模拟操作系统,加深学生对操作系统实现思路的理解,提高综合运用所学知识的能力,以及培养系统设计能力,为以后更进一步的设计和分析系统打下坚实的基础。
1.3意义
通过在平时原有认识的基础上又进一步的系统的学习了操作系统的相关知识,强化了自己的认知。
通过本模拟操作系统的设计使自己更加直观的理解了操作系统的相关知识,大大提高了自己分析问题和解决问题的能力,为以后的进一步学习起到了很好的铺垫。
1.4论文组织安排
本文安排如下:
第一章绪论。
介绍课题的背景、设计目标和意义。
第二章系统分析与设计。
介绍进程管理存储管理的设计要求以及总设计框架。
第三章系统详细设计。
介绍各个代码块的详细设计流程。
第四章问题与总结。
总结自己设计过程以及设计中遇到的主要问题及解决方法。
2系统分析与设计
2.1进程管理要求
2.1.1进程状态
由于本系统采用的是基于时间片调度算法模拟进程的运行过程,所以设定的进程基本状态为就绪运行、运行状态和完成状态。
如图2-1
图2-1进程基于时间片轮转算法的基本状态
2.1.2进程控制块
进程控制块PCB(ProcessControlBlock)是进程最重要的数据结构,它用于描述和控制进程,是进程存在的唯一标识。
进程控制块内容有进程标示符、处理机状态、进程调度信息、进程控制信息。
本系统采用链式方式来组织进程控制块。
把具有同一状态的进程控制块链接成一个队列,这样就形成了就绪状态、运行状态和完成状态。
2.1.3进程创建
一旦操作系统接收到用户输入的创建命令,便调用进程创建函数按下列方式为用户创建一个新进程。
(1)申请一个空白的PCB。
(2)为进程分配内存。
(3)初始化PCB中的内容。
(4)将PCB插入到就绪队列,等待调度。
2.1.4进程调度
进程调度采用时间片轮转调度算法,时间片大小由用户自己定义。
进程调度函数主要完成下列工作:
(1)从就绪队列中选择队首进程插入到运行队列。
(2)修改PCB中的信息。
(3)假如进程运行完便插入到完成队列,从就绪队列取下一进程到运行队列。
(4)否则将这一进程插入到就绪队列队尾,等待下一次调度。
2.1.5进程撤销
进程撤销函数主要完成下列工作:
(1)将进程控制块PCB移出队列。
(2)释放进程所占内存。
(3)将撤销信息显示在屏幕上。
2.2存储管理要求
2.2.1内存分配
由于本系统采用的内存分配策略是基本分页存储管理方式,又称为离散分配方式。
所以有必要对内存进行分块和初始化。
采用二维数组模拟基本分页存储。
内存分配主要完成下列工作:
(1)初始化内存数组,将其分割成一组不连续的块。
(2)为进程分配用户提出请求的页数。
(3)将分配的页号和块号显示在屏幕上。
2.2.2回收内存
当进程运行完释放内存时,系统根据用户的要求从相应的链表上摘下,然后释放内存数组的数据,此时可能出现两种情况。
(1)回收的PCB在就绪队列。
(2)回收的PCB在完成队列。
2.3总体设计要求
本系统包括如下代码块:
(1)主函数模块。
调用初始化代码块和菜单代码块。
(2)初始化代码块。
初始化内存数组。
(3)菜单代码块。
调用创建进程、查看内存、运行进程、撤销进程代码块。
(4)创建进程代码块。
创建并初始化进程控制块以及分配内存空间。
(5)查看内存代码块。
查看内存的分配情况。
(6)运行进程代码块。
采用时间片轮转调度算法调度进程运行。
(7)结束进程代码块。
结束进程并释放其占用的内存空间。
函数之间的调用的关系如图2-3所示。
图2-3总体设计模块
3系统详细设计
3.1全局变量
系统代码中定义的一些全局变量
#defineN100//共有100个内存块
intprocess[N][N+1];//存放每个进程的页表
intblock[N];//内存块状态标志数组,0:
空闲,1:
使用
intblockCount;//记录当前内存剩余空间
intprocessCount;//记录当前进程数
boolflag=true;
intM;
typedefstructnode{
intpid;
intround;
intneedtime;
intcputime;
intcount;
intstate;
structnode*next;
}PCB;
PCB*finish,*ready,*tail,*run;
3.2内存初始化
3.2.1内存定义
定义内存块共有N个,初始化后的内存空间应该有一部分已经被使用,这可以用系统提供的随机数函数rand()完成。
假定内存空间已经按块划分,目标程序无需关心内存块大小等底层细节,只需按算法对内存块进行分配即可。
采用二维数组3-2-1来模拟进程使用内存块情况。
用一个内存状态标志数组来记录内存的占用情况。
图3-2-1内存二维数组示意图
3.2.2主要代码
voidinit()
{
inti,j;
for(i=0;iblock[i]=0;
for(i=0;i<80;i++)
block[rand()%(N-1)]=1;
blockCount=0;
for(i=0;iif(block[i]==0)
blockCount++;
for(i=0;iprocess[i][0]=0;
for(j=1;jprocess[i][j]=-1;
}
processCount=0;
printf("初始化结果如下:
");
output();
flag=false;
}
3.2.3测试结果
图3-2-2
3.3创建进程
3.3.1进程结构PCB的描述
每个进程用一个进程控制块(PCB)表示。
进程控制块包含如下信息:
进程名、轮数、需要运行时间、已用CPU时间、进程状态、指针。
typedefstructnode
{
intpid;
intround;
intneedtime;
intcputime;
intcount;
intstate;
structnode*next;
}PCB;
3.3.2进程队列的描述
进程队列包括就绪队列、运行队列和完成队列,指向进程队列的指针有就绪头队列指针ready、运行队列头指针run、完成队列头指针finish以及队列尾指针tail。
图3-3-2把具有统一状态的PCB用链接字链接成一个队列。
现做如下定义。
PCB*finish,*ready,*tail,*run;
图3-3-2PCB链接队列示意图
3.3.3流程图
图3-3-3创建进程流程图
3.3.4主要代码
boolcreateProcess()
{
intna;
intpages,k=0;
PCB*p;
inttime;
//charna[10];
ready=NULL;
finish=NULL;
run=NULL;
printf("输入进程数:
");
scanf("%d",&M);
inta[N];
for(intj=0;j{
loop:
printf("请输入进程号(小于%d)和运行时间和所需页面数:
",N);
scanf("%d%d%d",&na,&time,&pages);
a[j]=na;
for(intk=0;k{
if(a[k]==a[k+1])
{
printf("进程号输入重复,请重新输入!
\n\n");
gotoloop;
}
}
if(na>99)
{
printf("错误!
进程号过大!
\n");
gotoloop;
}
if(pages>blockCount)
{
printf("错误!
内存分配失败,没有你要求的进程块数!
\n");
returnfalse;
}
blockCount-=pages;
process[na][0]=pages;
for(inti=1;i<=pages;i++)
{
while(block[k]==1&&k<100)
k++;
process[na][i]=k;
block[k]=1;
k++;
}
p=(PCB*)malloc(sizeof(PCB));
//strcpy(p->pid,pid);
p->pid=na;
p->cputime=0;
p->needtime=time;
p->state='W';
p->round=0;
p->count=0;
if(ready!
=NULL)
insert(p);
else
{
p->next=ready;
ready=p;
tail=ready;
}
processCount++;
printf("创建新进程成功!
\n\n");
}
returntrue;
}
3.3.5测试结果
图3-3-5
3.4查看内存
3.4.1页表
在分页系统中,允许将进程的各个页离散的存储在内存的不同物理块中,但系统应能保证进程的正确运行,即能在内存中找到每个页面对应的物理块。
为此,系统又为每个进程建立了一张页面映像表,简称页表。
在进程地址空间内的所有页(0~n),依次在页表中有一页表项,其中记录了相应页在内存中对应的物理块号,见图3-4-1。
在配置了页表后,进程执行时通过查找页表,即可找到每页在内存中的物理块号。
内存输出函数output()主要功能是输出内存初始化下的内存占用信息以及在系统执行撤销进程函数endProcess()后输出内存占用情况。
图3-4-1页表
3.4.2流程图
图3-4-2查看内存流程图
3.4.3主要代码
voidoutput()
{
printf("\n内存总量:
%d块,已用空间:
%d块,剩余空间:
%d块,进程总数:
%d个\n",N,N-blockCount,blockCount,processCount);
if(flag&&blockCount{
printf("已使用的内存块(%d):
\n",N-blockCount);
for(intk=0,count=0;k{
if(block[k]==1)
printf("%2d",k,++count);
if(count==10)
{
putchar('\n');
count=0;
}
}
putchar('\n');
}
if(processCount>0)
{
intid;
printf("请输入要查看的进程号:
");
scanf("%d",&id);
printf("内存详细使用情况如下:
\n");
if(process[id][0]>0)
{
printf("**************\n");
printf("进程号:
%d\n",id);
printf("|------------|\n");
printf("|页号|块号|\n");
printf("|------------|\n");
for(intj=1,count=0;j<=process[id][0];j++)
{
printf("|%2d|%2d|\n",count,process[id][j],count++);
printf("|------------|\n");
}
printf("***输出结束***\n");
}
}
else
printf("当前内存无进程!
\n");
putchar('\n');
}
3.4.4测试结果
图3-4-4
3.5运行进程
3.5.1时间片轮转调度算法
所有就绪进程按FCFS排成一个队列,总是把处理机分配给队首的进程,各进程占用CPU的时间片相同。
即将CPU的处理时间划分成一个个相同的时间片,就绪队列的诸进程轮流运行一个时间片。
当一个时间片结束时,如果运行进程用完它的时间片后还未完成,就强迫运行机制进程让出CPU,就把它送回到就绪队列的末尾,等待下一次调度。
同时,进程调度又去选择就绪队列中的队首进程,分配给它一时间片,以投入运行。
直至所有的进程运行完毕。
3.5.2算法工作安排
(1)用户可以自行输入进程的数量,每一个进程由进程控制块(PCB)表示,各种队列均采用链表数据结构。
(2)按照进程输入的先后顺序排成一个队列。
再设一个队首指针指向第一个到达进程的首址。
(3)执行处理机调度时,开始选择队首的第一个进程运行。
另外,再设一个当前运行进程的指针,指向当前正在运行的进程。
(4)在规定的时间片内进程是根据先来先服务的方式配列的,每个进程只运行时间片大小的时间然后转到下一个进程运行,直到所有进程运行完为止。
3.5.3流程图
图3-5-3(a)进程运行流程图
图3-5-3(b)prt输出函数流程图
3.5.4主要代码
boolRoundrun()
{
inttimeSlice;
if(processCount<1)
{
printf("当前程序无进程,请重新输入!
\n\n");
return0;
}
printf("请输入时间片的大小:
");
scanf("%d",&timeSlice);
printf("时间片轮转法输出信息\n");
printf("*****************************************************************************\n");
run=ready;
ready=ready->next;
tail->next=run;
run->state='R';
prt();
while(run!
=NULL)
{
run->cputime=run->cputime+timeSlice;
run->needtime=run->needtime-timeSlice;
run->round+=