南通大学操作系统课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南通大学计算机科学与技术学院操作系统课程设计
报告书
设计题目操作系统模拟算法
专业班级网络工程121
学生姓名刘学生
学号**********
指导老师丁红
日期2014.06.30-2014.07.4
课程设计题目操作系统模拟算法
一、主要目的
操作系统是计算机系统中不可缺少的基本系统软件,主要用来管理和控制计算机系统的软硬件资源,以提高整个系统资源的利用率,并为用户提供一个方便、灵活、安全和可靠地使用计算机的工作环境。
主要目的就是在学习操作系统原理课程的基础上,以操作系统的基本原理与实现技术为主要内容,对操作系统各功能部分的可能实现算法,进行模拟,以便通过编程实验,加深对操作系统原理的理解和掌握。
二、设备与环境
1.硬件设备:PC机一台
2. 软件环境:安装Windows操作系统或者Linux操作系统,
并安装相关的程序开发环境,如C \visual C++\Java 等编程语言环境。
三、实验要求
书写实验报告,应该包括以下几项内容:
(1)实验题目
(2)数据结构及主要符号说明。
(3)程序流程图和源程序
(4)执行时,包括各个进程控制块的初始状态、运行时的进程名字、状态、就绪队列的进程排序。
(5)收获和心得及改进意见和见解。
三、总流程图
四、主界面效果截图
A、输入操作选项1 输入应用算法1
输入应用算法2
B、输入操作选项2 输入应用算法1
C、输入操作选项3 输入应用算法1
五、主界面显示部分算法
1)主界面显示
void main()
{
cout<<"**********************欢迎使用操作模拟系统***************************\n";
cout<<"请选择操作选项:\n";
cout<<"*1.处理机管理\n";
cout<<"*2.主存空间的分配与回收\n";
cout<<"*3.虚拟存储器管理\n";
OPTION1();
}
2)三个模块显示的部分代码
1)处理机管理部分
case 1 :
cout<<"\n********处理机管理********\n";
cout<<"1.先来先服务调度算法\n";
cout<<"2.时间片轮转法调度算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
/* cout<<"先来先服务算法"<<endl;*/
XLXFW();
main();
//先来先服务调度算法
break;
OPTION2();
case 2 :
//时间片轮转法调度算法
SJPLZ();
main();
break;
OPTION2();
case 3:main();
break;
}
break;
2)主存空间的分配与回收部分
case 2 :
cout<<"\n********主存空间的分配与回收********\n";
cout<<"1.首次适应算法\n";
cout<<"2.可变分区管理算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
SCSYF();
main();
//首次适应算法
break;
case 2 :
KBFQ();
main();
//可变分区管理算法
case 3:main();
break;
}
break;
3)虚拟存储器管理部分
case 3 :
cout<<"\n********虚拟存储器管理********\n";
cout<<"1.先进先出算法\n";
cout<<"2.LRU算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
XJXC();
main();
//先进先出算法
break;
case 2 :
LRU();
main();
//LRU算法
break;
case 3:
main();
cout<<endl;
break;
4)输入错误的部分代码
void OPTION3()
{
cout<<"请输入应用算法: ";
cin>>option2;
if(option2>=4||option2<=0)
{
cout<<"输入有误请重新输入!\n";
OPTION2();
}
}
六、三个模块分析
(一)处理机管理
A.先来先服务的调度算法
(1) 实验目的
在多道程序或多任务系统中,系统中同时处于就绪态的进程有若干个,也就是说能运行的进程数远远大于处理机个数。
为了使系统中的各进程能有条不紊地运行,必须选择某种调度策略,以选择一进程占用处理机。
要求学生设计一个模拟单处理机调度的算法,以加深对处理机调度的概念理解。
(2) 实验内容
先来先服务算法按照作业进入系统后备作业队列的先后次序来挑选作业,先进入系统的作业将优先被挑选进入主存,创建用户进程,分配所需资源,然后,移入就绪队列。
(1)用C语言(或其它语言,如Java)实现对N个进程采用某种进程调度算法(如
动态优先权调度)的调度。
(2)每个用来标识进程的进程控制块PCB可用结构来描述,包括以下字段:
✧进程标识数ID。
✧进程优先数PRIORITY,并规定优先数越大的进程,其优先
权越高。
✧进程已占用CPU时间CPUTIME。
✧进程还需占用的CPU时间ALLTIME。
当进程运行完毕时,
ALLTIME变为0。
✧进程的阻塞时间STARTBLOCK,表示当进程再运行
STARTBLOCK个时间片
后,进程将进入阻塞状态。
✧进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待
BLOCKTIME个
时间片后,将转换成就绪状态。
✧进程状态STATE。
✧队列指针NEXT,用来将PCB排成队列。
(3)优先数改变的原则:
✧进程在就绪队列中呆一个时间片,优先数增加1。
✧进程每运行一个时间片,优先数减3。
(4)在所设计的程序中应有显示或打印语句,能够显示或打印正在运行的进程名字、已运行时间、就绪队列中的进程名字等。
所有进程运行完成时,给出各进程的周转时间和平均周转时间。
(5)通过实验后的收获与体会及对实验的改进意见和见解。
(3)主要流程图
(4)实验结果
测试用例
c 2 3
d 3 10
(5)实验截图
(6)算法部分代码
void getInfo()
{
int num;
printf("\n请输入作业的个数:");
scanf("%d",&n);
for(num=0;num<n;num++)
{
p=(pcb1 *)malloc(sizeof(pcb1));
printf("依次输入:\nID 进程名到达时间服务时间\n");
scanf("%s\t%s\t%d\t%d",&p->ID,&p->name,&p->arrivetime,& p->servicetime);
if(head==NULL){head=p;q=p;time=p->arrivetime;}
if(p->arrivetime<time) time=p->arrivetime;
q->next=p;
p->starttime=0;
p->finishtime=0;
p->turnaroundtime=0;
p->weighedturnaroundtime=0;
p->next=NULL;
p->state='F';
q=p;
}
}
(7)实验结果分析
先来先服务算法顾名思义先到的先参与调度,本测试中按照a、b、c、d的顺序。
因为只有非抢占方式,所以先到的进程必须执行完来才能执行下一个进程,下一个进程的开始时间也就取决于到达时间和上一个进程的结束时间中较晚的一个,如c进程的到达时间是2,但是b进程的完成时间是12,所以c进程的开
始时间为12。
由实验结果可以看出,短作业c的带权周转时间竟高达4.33,而长作业d 的带权周转时间仅为2.20,据此可知,FCFS算法有利于CPU繁忙的作业,而不利于I/O繁忙型的作业(进程)。
B.时间片轮转法调度算法
(1)简单描述
调度程序每次把CPU分配给就绪队列首进程/线程使用规定的时间间隔,称为时间片,通常为10ms~200ms,就绪队列中的每个进程/线程轮流地运行一个时间片,当时间片耗尽时,就强迫当前运行进程/线程让出处理器,转而排列到就绪队列尾部,等待下一轮调度,所以,一个耗时型进程/线程需要经过多次轮转才能完成。
(2)程序设计实现
(3)主要流程图
(4)运行结果截图
(5)程序主要代码
void inputprocess()
{
PCB *p1,*p2;
int num;
printf("How many processes do you want to run:");
fprintf(f,"How many processes do you want to run:");
scanf("%d",&num);
fprintf(f,"%d\n",&num);
p1=&head_input;
p2=p1;
p1->next=new PCB;
p1=p1->next;
for(int i=0;i<num;i++)
{
printf("Input NO.%3d process pname:",i+1);
fprintf(f,"Input NO.%3d process pname:",i+1);
scanf("%s",p1->pname);
fprintf(f,"%s\n",p1->pname);
printf(" runtime:");
fprintf(f," runtime:");
scanf("%d",&(p1->runtime));
fprintf(f,"%d\n",&(p1->runtime));
printf(" arrivetime:");
fprintf(f," arrivetime:");
scanf("%d",&(p1->arrivetime));
fprintf(f,"%d\n",&(p1->arrivetime));
p1->runtime=(p1->runtime)*1000;
p1->arrivetime=(p1->arrivetime)*1000;
p1->state=R;
p1->next=new PCB;
p2=p1;
p1=p1->next;
}
delete p1;
p1=NULL;
p2->next=NULL;
}
(6)实验分析
时间片轮转法调度是一种剥夺式调度,系统耗费在进程/线程切换上的开销比较大,这个开销与时间片的大小有关。
如果时间片取值太小,将导致大多数进程/线程都不可能在一个时间片内运行完毕,就会切换频繁,开销显著增大,所以,从系统效率的角度来看,时间片取的大一点好;另一方面,时间片的长度较大,那么,随着就绪队列中进程/线程数目的增加,轮转一次所耗费的总时间加长,即对每个进程/线程的响应速度放慢,甚至时间片大到让进程/线程足以完成其所有任务,时间片轮转法调度便
退化成先来先服务算法了。
(二)主存空间的分配与回收
A.首次适应算法
(1)实验目的
主存是中央处理器能直接存取指令和数据的存储器,能否合理而有效地使用它在很大程度上将影响整个计算机系统的性能。
本实验主要熟悉主存的各种管理方法以及相应的分配与回收算法。
所谓分配,就是解决多道程序或多进程如何共享主存空间的问题,以便各个进程能获得所希望的主存空间,正确运行。
所谓回收,就是当进程运行完成时,将其所占用的主存空间归还给系统。
本实验帮助学生理解在不同的存储管理方式下,如何实现主存空间的分配与回收。
(2)实验内容
采用空闲区链法管理空闲区,并增加已分配区表。
分配算法采用首次适应法(内存空闲区的地址按照从小到大的自然顺序排列),实现内存的分配与回收。
(1) 、可变式分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区的个数是可以调整的。
当需要装入一个作业时,根据作业需要的贮存量,查看是否有足够的空闲空间,若有,则按需求量分割一部分给作业;若无,则作业等待。
随着作业的装入、完成,主存空间被分割成许多大大小小的分区。
有的分区被分配作业占用,有的分区空闲,例如,某时刻主存空间占用情况如图所示:
为了说明哪些分区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,如下图所示。
(2) 、当有一个新作业要求装入贮存时,必须查空闲区说明表,从中找出一个足够大的空闲区。
有时找到的空闲区可能大于作业的需求量,这时应将空闲区一分为二。
一个分给作业,另一个仍作为空闲区留在空闲区表中。
为了尽量减少由于分割造成的碎片,尽可能分配地地址部分的空闲区,将较大的空闲区留在高地址端,以利于大作业的装入。
为此在空闲区表中,按空闲区首地址从低到高进行登记。
(3) 、当一个作业执行完成时,作业所占用的分区应归还给系统。
在归还时,要考虑相邻空间区合并问题。
作业的释放区与空闲区的邻接分以下4种情况考虑:
A、释放区下邻空闲区;
B、释放区上邻空闲区;
C、释放区上下都与空闲区邻接;
释放区上邻空闲区不邻接;
(3)算法流程图
(4)算法部分代码
Partition * New_Process( Partition *list, Partition *FP) { //为新的进程分配资源
Partition *H,*P,*H1;
int Size,Name,L;
H=list;
H1=FP->next;
H=H->next;
printf("请输入新作业的名称和大小(整数):");
scanf("%d %d",&Name,&Size);
while(H)
{
if(!H) //表目已查完,无法分配
{
printf("\n已无空闲分区,本次无法分配!");
return list;
}
else{
if(H->IsUse==0) //空表目
//if(H->Par_Size>=Size) //大小满足,空闲分区大小》要分配的大小
if(H->Par_Size>=Size) //大小满足,
{
bool temp=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=(struct Partition *)malloc(sizeof(struct Partition)); //分配新的表目,处理一条数据,分配一次内存
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");
return list;
}
(5)运行结果截图
B.可变分区管理算法
(1)实验目的
请求页式存储管理方式是一种实现虚拟存储器的方式,是指在进程开始运行之前,不是装入全部页面,而是装入一个或零个页面,之后根据进程运行的需要,动态装入其它页面。
当内存空间已满,而又需要装入新的页面时,则根据某种算法淘汰某个页面,以便装入新的页面。
请求页式存储管理主要需要解决以下问题:系统如何获知进程当前所需页面不在主存;当发现缺页时,如何把所缺页面调入主存;当
主存中没有空闲的页框时,为了要接受一个新页,需要把老的一页淘汰出去,根据什么页面淘汰算法选择欲淘汰的页面。
(2)实验内容
该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。
该算法实现简单,只需把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针,称为替换指针,是他总是指向最老的页面。
但该算法与进程实际运行的规律不相适应,因为在进程中,有些页面经常被访问,比如,含有全局变量,常用函数,例程等的页面,FIFO算法并不能保证这些页面不被淘汰。
(3)算法流程图
(4)算法部分代码
void setfree()
{ int s,l,tag1=0,tag2=0,tag3=0,i,j;
printf("input free area startaddress:\n");
scanf("%d",&s);
printf("input free area size:\n");
scanf("%d",&l);
for(i=0;i<M;i++)
{
if(freeblock[i].startaddress==s+l&&freeblock[i].state==1)
{l=l+freeblock[i].size;
tag1=1;
for (j=0;j<M;j++)
if(freeblock[j].startaddress+freeblock[j].size==s&&freeblock[j].state==1)
{freeblock[i].state=0;
freeblock[j].size=freeblock[j].size+l;//////
tag2=1;
break;
}
if(tag2==0)
{ freeblock[i].startaddress=s;
freeblock[i].size=l;
break;
}
}
}
if(tag1==0)
{ for(i=0;i<M;i++)
if(freeblock[i].startaddress+freeblock[i].size==s&&freeblock[i].state==1) { freeblock[i].size=freeblock[i].size+l;///////
tag3=1;
break;
}
if(tag3==0)
for(j=0;j<M;j++)
if(freeblock[j].state==0)
{ freeblock[j].startaddress=s;
freeblock[j].size=l;//////////
freeblock[j].state=1;
break;
}
}
}
(5)程序运行结果截图
(三)虚拟存储器管理
A.先进先出算法
(1)实验目的:
在分页虚拟存储系统中,当硬件发出缺页中断后转操作系统处理缺页中断。
如果主存中已经无空闲块,采用FIFO进程缺页处理。
(2)实验内容
每访问一个地址时,首先要计算该地址所在的页的页号,然后查页表,判断该页是否在主存——如果该页已在主存,则打印页表情况;
如果该页不在主存且页表未满,则调入一页并打印页表情况;如果该页不足主存且页表已满,则按 FIFO页面淘汰算法淘汰一页后调入所需的页,打印页表情况;逐个地址访问,直到所有地址访问完毕。
(3)算法流程图
(4)算法部分代码
void XJXC()
{
int ym[h],i,j,q,mem[m]={0},table[m][h];
char flag,f[h];
printf("请输入页面访问序列(内存块数m=4,页号h=20):\n");
printf("\n");
for(i=0;i<h;i++)
scanf("%d",&ym[i]);
printf("\n");
for(i=0;i<h;i++) //查页表,看是否缺页
{
q=0;
while((ym[i]!=mem[q])&&(q!=m))
q++;
if(q==m) flag='#'; //缺页,则置标志flag为'*' else flag=' ';
if(flag=='#')
{
for(j=m-1;j>0;j--) //淘汰最先调入的页面调入当前访问的mem[j]=mem[j-1];
mem[0]=ym[i];
}
for(j=0;j<m;j++)
table[j][i]=mem[j];
f[i]=flag;
}
(5)程序运行结果截图
B.LRU算法
(1)算法描述及实验目的
最近最少使用页面替换算法(即LRU算法)淘汰的页面是在最近一段时间内最久未被访问的那一页,它是基于程序局部性原理来考虑的,认为那些刚被使用过的页面可能还要立即被使用,而那些在较长时间内未被使用的页面可能不会立即使用。
为了能准确地淘汰最近最少使用的页面,必须维护一个特殊的队列——页面淘汰队列,此队列存放当前在主存中的页号,每访问一次时就调整一次,使队列尾总是指向最近访问的页,队列头就是最近最少使用的页。
为了使大的进程(其地址空间超过主存可用空间)或多个进程的地址空间之和超过实际主存空间时,仍能运行,引入了虚拟存储器的概念。
使进程的一部分地址空间在主存,另一部分在辅存,由操作系统实现多级存储器的自动管理,实现主存空间的自动覆盖。
模拟请求分页虚拟存储器管理技术中的硬件地址变换、缺页中断以及页式淘汰算法,处理缺页中断。
(2)实验内容
当采用LRU算法时,用一个数组P构成堆栈,堆栈中各个元素为进程已在主存的页号,为了进行页面置换,可设置一个栈指针HEAD,初始化为0。
假定分配给每个进程的内存块数固定不变,为M。
当队列满需要淘汰时,操作系统选择栈底的元素淘汰,其他元素向下移一个位置,将新调入页放HEAD指示的栈顶。
当访问的页在栈中时,还应调整页从当前位置到栈顶。
(3)算法流程图
(4)程序部分代码
void LRU()
{
int ym[Q],i,j,q,mem[W]={0},table[W][Q];
char flag,f[Q];
printf("请输入页面访问序列(内存块数W=5,页号Q=20)\n");
for(i=0;i<Q;i++)
scanf("%d",&ym[i]);
printf("\n");
for(i=0;i<Q;i++) //查页表,看是否缺页{
q=0;
while((ym[i]!=mem[q])&&(q!=W)) q++;
if(q==W) flag='*'; //缺页,则置标志flag为'*' else flag=' ';
for(j=q;j>0;j--)
mem[j]=mem[j-1];
mem[0]=ym[i];
for(j=0;j<W;j++)
table[j][i]=mem[j];
f[i]=flag;
}
(5)运行结果截图
七、实验体会与心得
先来先服务算法比较容易实现,但效率低。
它没有考虑各个作业运行特性和资源要求的差异。
这种算法对短作业不利,短作业执行时间很短,等待时间却较长,带权周转时间很大。
时间片轮转法调度是一种剥夺式调度,系统耗费在进程/线程切换上的开销比较大,这个开销与时间片的大小有关。
如果时间片取值太小,将导致大多数进程/线程都不可能在一个时间片内运行完毕,就会切换频繁,开销显著增大
在程序中巧妙地设计调用函数和函数嵌套来简化程序,例如在查找未执行进程和对未执行进程执行时分别设计了void fcfs()和void run_fcfs(),多个进程运行时均要调用这两个函数,简化了代码。
另外,在编写程序之前,由于先画来流程图,对应流程图的顺序来实现程序,能对程序有个全局的把握,提高了编写速度,减少了错误。
一些常用的错误基本可以查阅资料把它解决,增加了自己动手解决问题的能力。
通过此次的实验,让我对内存分配中首次适应算法更加熟悉,通过编程模拟实现操作系统的可变分区存储管理的功能,一方面加深对原理的理解,另一方面提高根据已有原理通过编程解决实际问题的能力,为进行系统软件开发和针对实际问题提出高效的软件解决方案打下基础。
另外,在编写程序之前,由于先画来流程图,对应流程图的顺序来实现程序,能对程序有个全局的把握,提高了编写速度,减少了错误。
一些常用的错误基本可以查阅资料把它解决,增加了自己动手解决问题的能力。
敢于攻坚,越是难的问题,越是要有挑战的心理。
这样就能够达到废寝忘食的境界。
当然这也是不提倡熬夜的,毕竟有了精力才能够打持久战。
但是做课设一定要有状态,能够在吃饭,睡觉,上厕所都想着要解决的问题,这样你不成功都难。
同学间的讨论,这是很重要的。
老师毕竟比较忙。
对于课程设计最大的讨论伴侣应该是同学了。
能和学长学姐讨论当然再好不过了,没有这个机会的话,和自己班上同学讨论也是能够受益匪浅的。
大家都在研究同样的问题,讨论起来,更能够把思路理清楚,相互帮助,可以大大提高效率。
通过这一周的课程设计,确实学到了书本上学不到的知识。
让我对操作系统有了更进一步的了解,更加了解了操作系统的运行过程。
也锻炼了我遇到什么事要敢于迎难而上,敢于动脑,敢于思考的能力。
也告诉自己遇到事情要去找答案,上网、问同学、请教老师等等。
八、参考文献
附源程序(可运行调试)
#include<iostream.h>
int option1,option2;
#include<stdlib.h>
#define N 10
#include<stdio.h>
#include<conio.h>
#include "stdio.h"
#define M 5
#include <STDIO.H>
#include <STDLIB.H>
int MAX_SEGMENT=10;
#include "stdio.h"
#define h 20
#define m 4
#include "stdio.h"
#define Q 20
#define W 5
void OPTION1();
void OPTION2();
void OPTION3();
void XLXFW();
void SJPLZ();
void SCSYF();
void KBFQ();
void XJXC();
void LRU();
void main()
{
cout<<"**********************欢迎使用操作模拟系统***************************
\n";
cout<<"请选择操作选项:\n";
cout<<"*1.处理机管理\n";
cout<<"*2.主存空间的分配与回收\n";
cout<<"*3.虚拟存储器管理\n";
OPTION1();
}
void OPTION1()
{
cout<<"请输入操作选项: ";
cin>>option1;
if(option1>=4||option1<=0)
{
cout<<"输入有误请重新输入!\n";
OPTION1();
}
else
OPTION2();
}
void OPTION2()
{
switch(option1)
{
case 1 :
cout<<"\n********处理机管理********\n";
cout<<"1.先来先服务调度算法\n";
cout<<"2.时间片轮转法调度算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
/* cout<<"先来先服务算法"<<endl;*/
XLXFW();
main();
//先来先服务调度算法
break;
OPTION2();
case 2 :
//时间片轮转法调度算法
SJPLZ();
main();
break;
OPTION2();
case 3:main();
break;
}
break;
case 2 :
cout<<"\n********主存空间的分配与回收********\n";
cout<<"1.首次适应算法\n";
cout<<"2.可变分区管理算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
SCSYF();
main();
//首次适应算法
break;
case 2 :
KBFQ();
main();
//可变分区管理算法
case 3:main();
break;
}
break;
case 3 :
cout<<"\n********虚拟存储器管理********\n";
cout<<"1.先进先出算法\n";
cout<<"2.LRU算法\n";
cout<<"3.返回主界面\n";
cout<<endl;
OPTION3();
switch(option2)
{
case 1 :
XJXC();
main();
//先进先出算法
break;
case 2 :
LRU();
main();
//LRU算法
break;
case 3:
main();
cout<<endl;
break;
}
break;
}
}
void OPTION3()
{
cout<<"请输入应用算法: ";
cin>>option2;
if(option2>=4||option2<=0)
{
cout<<"输入有误请重新输入!\n";
OPTION2();
}
}
////////////////////////////////源程序//////////////////////////////
/////先来先服务算法调度///////////////////
typedef struct PCB1
{
char ID[3];
char name[10];
char state;
int arrivetime;
int starttime;
int finishtime;
int servicetime;
float turnaroundtime;
float weighedturnaroundtime;
struct PCB1 *next;
}pcb1;
int time;
int n;
pcb1 *head=NULL,*p,*q;
void run_fcfs(pcb1 *pl)
{
time=pl->arrivetime>time?pl->arrivetime:time;
pl->starttime=time;
printf("\n 现在时间是%d,开始运行作业%s\n",time,pl->name);
time+=pl->servicetime;
pl->state='T';
pl->finishtime=time;
pl->turnaroundtime=pl->finishtime-pl->arrivetime;
pl->weighedturnaroundtime=pl->turnaroundtime/pl->servicetime;
printf("ID 到达时间开始时间服务时间完成时间周转时间带权周转时间\n");
printf("%s%6d%10d%10d%8d%10.1f%10.2f\n",
pl->ID,pl->arrivetime,pl->starttime,pl->servicetime,pl->finishtime,
pl->turnaroundtime,pl->weighedturnaroundtime);
}
void fcfs()
{
int i,j;
p=head;
for(i=0;i<n;i++)
{
if(p->state=='F')
{
q=p;
run_fcfs(q);
}
p=p->next;
}
}
void getInfo()
{
int num;
printf("\n请输入作业的个数:");
scanf("%d",&n);
for(num=0;num<n;num++)
{
p=(pcb1 *)malloc(sizeof(pcb1));
printf("依次输入:\nID 进程名到达时间服务时间\n");
scanf("%s\t%s\t%d\t%d",&p->ID,&p->name,&p->arrivetime,&p->servicet ime);
if(head==NULL){head=p;q=p;time=p->arrivetime;}
if(p->arrivetime<time) time=p->arrivetime;
q->next=p;
p->starttime=0;
p->finishtime=0;
p->turnaroundtime=0;
p->weighedturnaroundtime=0;
p->next=NULL;
p->state='F';
q=p;
}
}
void XLXFW()
{ printf(" ");
printf(" 先来先服务算法");
getInfo();
p=head;
fcfs();
}
////时间片轮转法调度///////////////////////////////// typedef struct pcb
{
char pname[N];
int runtime;
int arrivetime;
char state;
struct pcb*next;
}PCB;
PCB head_input;
PCB head_run;
PCB *pcb_input;
static char R='r',C='c';
unsigned long current;
void inputprocess();
int readydata();
int runprocess();
int readyprocess();
FILE *f;
int readyprocess()
{
while(1)
{
if(readydata()==0)
return 1;
else
runprocess();
}
}
int readydata()
{
if(head_input.next==NULL)
{
if(head_run.next==NULL)
return 0;
else
return 1;
}
PCB *p1,*p2,*p3;
p1=head_run.next;
p2=&head_run;
while(p1!=NULL)
{
p2=p1;
p1=p2->next;
}
p1=p2;
p3=head_input.next;
p2=&head_input;
while(p3!=NULL)
{
if(((unsigned long)p3->arrivetime<=current)&&(p3->state==R))
{
printf("time is %4d;Process %s start,\n",\
(current+500)/1000,p3->pname);
fprintf(f,"time is %4d;Process %s start,\n",\
(current+500)/1000,p3->pname);
p2->next=p3->next;
p3->next=p1->next;
p1->next=p3;
p3=p2;
}
p2=p3;
p3=p3->next;
}
return 1;
}
int runprocess()
{
PCB *p1,*p2;
if(head_run.next==NULL)
{
current++;
return 1;
}
else
{
p1=head_run.next;
p2=&head_run;
while(p1!=NULL)
{
p1->runtime--;
current++;
if(p1->runtime<=0)
{
printf("Time is %4d;process %s end.\n",(current +500)/1000,p1->pname);
fprintf(f,"Time is %4d;process %s end.\n",(current +500)/1000,p1->pname);
p1->state=C;
p2->next=p1->next;
delete p1;
p1=NULL;
}
else{
p2=p1;
p1=p2->next;
}
}
return 1;
}
}
void inputprocess()
{
PCB *p1,*p2;
int num;
printf("How many processes do you want to run:");
fprintf(f,"How many processes do you want to run:");
scanf("%d",&num);
fprintf(f,"%d\n",&num);
p1=&head_input;
p2=p1;
p1->next=new PCB;
p1=p1->next;
for(int i=0;i<num;i++)
{
printf("Input NO.%3d process pname:",i+1);
fprintf(f,"Input NO.%3d process pname:",i+1);
scanf("%s",p1->pname);
fprintf(f,"%s\n",p1->pname);
printf(" runtime:");
fprintf(f," runtime:");
scanf("%d",&(p1->runtime));
fprintf(f,"%d\n",&(p1->runtime));
printf(" arrivetime:");
fprintf(f," arrivetime:");
scanf("%d",&(p1->arrivetime));
fprintf(f,"%d\n",&(p1->arrivetime));
p1->runtime=(p1->runtime)*1000;
p1->arrivetime=(p1->arrivetime)*1000;
p1->state=R;
p1->next=new PCB;
p2=p1;
p1=p1->next;
}
delete p1;
p1=NULL;
p2->next=NULL;
}
void SJPLZ()
{ printf(" 时间片轮转法");
f=fopen("result.txt","w");
printf("\ntime 1=1000 time slice\n");
fprintf(f,"\ntime 1=1000 time slice\n");
current=0;
inputprocess();
readyprocess();
getch();
fclose(f);
}
/////////////////首次适应法////////////
struct Partition //分区表目
{
int Par_Size; //分区大小
int Par_No; //分区序号或者名字
int Addr; //分区地址
int IsUse; //分区使用情况,0表示空闲,1表示使用Partition *pri; //前向指针
Partition *next; //后向指针
};
Partition * Int()//函数,返回Partition类型指针
{ //初始化空闲分区表
Partition *list,*H,*H1;
list=(struct Partition *)malloc(sizeof(struct Partition));
list->next=NULL;
H=list;
if(!list)
{
printf("\n错误,内存初始化分配失败!程序结束");
exit(1);
}
H1=(struct Partition *)malloc(sizeof(struct Partition));
printf("请预先输入分区总大小(以KB为单位):");
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
return list;
}
Partition * InitFP()
{ //初始化已分配分区表
Partition *FP,*F,*H;
int i;
FP=(struct Partition *)malloc(sizeof(struct Partition));
FP->next=NULL;
H=FP;
for(i=0;i<10;i++)
{
F=(struct Partition *)malloc(sizeof(struct Partition));
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;
}
return FP;
}
Partition * New_Process( Partition *list, Partition *FP)
{ //为新的进程分配资源
Partition *H,*P,*H1;
int Size,Name,L;
H=list;
H1=FP->next;
H=H->next;
printf("请输入新作业的名称和大小(整数):");
scanf("%d %d",&Name,&Size);
while(H)
{
if(!H) //表目已查完,无法分配
{
printf("\n已无空闲分区,本次无法分配!");。