操作系统大作业.docx
《操作系统大作业.docx》由会员分享,可在线阅读,更多相关《操作系统大作业.docx(15页珍藏版)》请在冰点文库上搜索。
![操作系统大作业.docx](https://file1.bingdoc.com/fileroot1/2023-7/21/af988c54-03bd-485a-a089-b0f23f3ca476/af988c54-03bd-485a-a089-b0f23f3ca4761.gif)
操作系统大作业
操作系统实验报告
进程调度实验
一.实验题目
用C语言编写和调试一个进程调度程序,模拟进程调度过程。
调度算法采用优先数算法和先来先服务算法。
二.目的要求
1.把理论与实践紧密结合,加深对进程的概念及进程调度算法的理解。
取得较好的学习效果
2.加深对操作系统课程的理解。
使学生更好地掌握操作系统的基本概念、基本原理、及基本功能,具有分析实际操作系统、设计、构造和开发现代操作系统的基本能力。
3.培养学生的系统程序设计能力。
三.实验内容
设计一个有N个进程并行的进程调度程序。
其中:
1)进程调度算法:
采用最高优先数优先的调度算法分配处理机和先来先服务算法来排队,总的过程采用时间片轮转算法。
2)每个进程有一个进程控制块(PCB)表示。
进程控制块可以包含如下信息:
进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态。
3)进程的优先数及需要的运行时间可以事先人为地指定。
进程的到达时间为进程输入的时间。
4)进程的运行时间以时间片为单位进行计算。
5)每个进程的状态可以是就绪W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
6)就绪进程获得CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
7)果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程;如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入相应优先级就绪队列等待CPU。
8)每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
9)重复以上过程,直到所要进程都完成为止。
四.整体功能设计
五.进程调度流程图:
Y
EXIT
N
N
Y
六.C语言编程实现及数据结构
6.1C程序见报告后面的代码
6.2数据结构
6.2.1在实验中共有8个进程。
进程优先级为1到3,进程状态为:
“wait”,“run”,“finish”中的一种。
6.2.2实验中PCB数据结构:
#definefinish-1
#definewait0
#definerun1
typedefstructPCB0{
charname[20];//进程名
intpriorit;//优先权
intreach_time;//到达时间
intall_time;//需要运行时间
intused_time;//已用时间
intstate;//进程状态
structPCB0*next;
}PCBS;
6.3实验中使用到的进程PCB:
PCBS
{"a1",3,0,6,0,wait,NULL},
{"a2",1,5,5,0,wait,NULL},
{"a3",1,12,4,0,wait,NULL},
{"a4",3,13,5,0,wait,NULL},
{"a5",2,15,5,0,wait,NULL},
{"a6",2,18,3,0,wait,NULL},
{"a7",3,21,5,0,wait,NULL},
{"a8",1,22,4,0,wait,NULL};
七.使用说明
只需把程序开始的PCBS类型的数组初始化为要将进行调度的作业队列即可。
再运行程序,程序会把运行过程中各PCB的状态输出到桌面上的“pcb.txt”中。
可能有些电脑的桌面位置与程序里设置的位置不同,这时只需改变相关路径就行了。
八.结果分析
作业进入内存时按优先级在相应优先级队列中排队,在本程序中有三个优先级,所以设置了三个就绪队列。
给不同优先级的进程在分配处理机时,高优先级队列中的进程优先分配到处理机。
在分配给它的时间片用完后,如果它不是最低优先级,则把它降一级,并插入到相应优先级队列队尾,如果它是最低优先级,则直接把它插入到队尾。
给同一优先级队列中的进程分配处理机时,按先来先服务的方式分配处理机。
从实验过程输出的进程调度信息中,可以明显的看出上述处理机分配原则。
这种分配方式下,高优先级的进程经过几次运行后优先级都会递减到1,用这种方法能保证每个进程都能分配到处理机,但是,由于优先级递减和先来先服务,使得一些高优先级耗时长的进程不利。
因为最后所有进程都在最低优先级队列里排队,一方面使最低优先级队列过长,另一面使这种调度方式接近基于时间片的先来先服务调度方式。
所以,可以在进程控制块PCB中设置一项,利用该项确定该进程的优先级是否需要递减。
这就可以改进原始调度方式的一些缺点,但这又可能使得低优先级的进程长时间得不到响应,使系统实时性降低。
九.设计体会
通过本次实验使我对进程调度的两种方式---先来先服务算法和最高优先数优先的调度算法有了比以前更深入的理解。
通过本次操作系统实验还使我复习了C语言的使用,特别是C中函数和指针的使用。
为了模拟作业从进入内存到运行完毕的过程,程序中使用链表作为数据结构,使用到了两级指针。
我认为操作系统课程是一个实践性很强的课程,为了将理论用于实践必须培养学生的系统程序设计能力,因此,操作系统实验是的一个非常重要的环节。
通过操作系统上机实验,既可以加深对理论的理解,又可以加强将算法用程序设计语言表达的能力。
一十.C语言代码
运行环境:
visualstudio2008
//OS2.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include"stdio.h"
#include"string.h"
#include"stdlib.h"//For_MAX_PATHdefinition
#include"malloc.h"
#defineN8
#definefinish-1
#definewait0
#definerun1
//定义进程结构体
typedefstructPCB0{
charname[20];//进程名
intpriorit;//优先权
intreach_time;//到达时间
intall_time;//需要运行时间
intused_time;//已用时间
intstate;//进程状态
structPCB0*next;
}PCBS;
//子函数区域开始
//链表创建
PCBS*joblistcreate(PCBS*PCB)
{
PCBS*head=NULL,*last=NULL,*p0=NULL;
p0=PCB;
//开辟节点
inti=1;
head=p0;
last=p0;
p0=&PCB[1];
while(ilast->next=p0;
last=p0;
//开辟下一个节点
if(ip0=&PCB[i+1];
i++;
}
returnhead;
}
//进程插入
voidpushpro(PCBS**head,PCBS**head1,PCBS**last1)
{
PCBS*p=NULL;
if(*head1==NULL)
{
*head1=*head;
*last1=*head;
*head=(*head)->next;
(*last1)->next=NULL;
}
else
{
p=*head;
*head=p->next;
(*last1)->next=p;
*last1=p;
(*last1)->next=NULL;
}
}
//删除进程
voidpro_over(PCBS**head,PCBS**last)
{
PCBS**p0=NULL;
p0=head;
(*head)=(*p0)->next;
if((*head)==NULL)
(*last)=NULL;
}
//进程循环
voidproloop(PCBS**head,PCBS**last,PCBS**head1,PCBS**last1)
{
PCBS*p;
p=*head;
if(*head==*head1)
{
if(*head1==*last1)
return;
else
{
*head=(*head)->next;
(*last1)->next=p;
(*last1)=p;
(*last1)->next=NULL;
return;
}
}
*head=(*head)->next;
if((*head)==NULL)
(*last)=NULL;
if((*head1)==NULL)
{
*head1=p;
*last1=p;
}
else
{
(*last1)->next=p;
*last1=p;
(*last1)->next=NULL;
}
}
//链表打印
voidlistprint(PCBS*head,FILE*fp)
{
charstate[10];
PCBS*p0=NULL;
p0=head;
while(p0!
=NULL)
{
switch(p0->state)
{
case-1:
strcpy(state,"finish");
break;
case0:
strcpy(state,"wait");
break;
case1:
strcpy(state,"run");
break;
}
fprintf(fp,"进程名%s,优先级%d,状态%s\n",p0->name,p0->priorit,state);
p0=p0->next;
}
}
//打印此刻的运行进程,等待进程
voidstatus(PCBS*head3,PCBS*head2,PCBS*head1,inttime,FILE*fp)
{
//打印此刻的运行进程,等待进程
fprintf(fp,"############------time=%d------############\n",time-1);
listprint(head3,fp);
listprint(head2,fp);
listprint(head1,fp);
}
//运行进程
voidrunning(PCBS**head,PCBS**last,PCBS**head1,PCBS**last1,inttime,FILE*fp,PCBS*L3,PCBS*L2,PCBS*L1)
{
PCBS**p0=NULL;
p0=head;
(*head)->used_time=(*head)->used_time+1;
(*head)->state=run;
status(L3,L2,L1,time,fp);
if((*head)->priorit>1)
(*head)->priorit=(*head)->priorit-1;
if((*head)->used_time>=(*head)->all_time)
{
(*head)->state=finish;
pro_over(head,last);
}
else
{
(*head)->state=wait;
proloop(head,last,head1,last1);
}
}
//子函数区域完
int_tmain(intargc,_TCHAR*argv[])
{
inttime=0;//系统时钟
FILE*fp;//文件指针
PCBSPCB[]={{"a1",3,0,6,0,wait,NULL},{"a2",1,5,5,0,wait,NULL},{"a3",1,12,4,0,wait,NULL},{"a4",3,13,5,0,wait,NULL},{"a5",2,15,5,0,wait,NULL},
{"a6",2,18,3,0,wait,NULL},{"a7",3,21,5,0,wait,NULL},{"a8",1,22,4,0,wait,NULL}};//系统作业队列
puts("\n*********************************\n");
printf("START!
\n");
//文件写入
if((fp=fopen("C:
\\Users\\Administrator\\Desktop\\pcb.txt","at+"))==NULL)
printf("\nerro!
\n");
fprintf(fp,"programrunningimformation!
\n");
//建立作业队列
PCBS*head=NULL,*last=NULL,*head1=NULL,*last1=NULL,*head2=NULL,*last2=NULL,*head3=NULL,*last3=NULL;
PCBS*p0=NULL;
//创建作业队列
head=joblistcreate(PCB);
while(head!
=NULL||head1!
=NULL||head2!
=NULL||head3!
=NULL)
{
printf("time=%d\n",time);
//查看有无进程进入,若有则插入相应队列
if((head)&&(head->reach_time<=time))
{
switch(head->priorit)
{
case3:
pushpro(&head,&head3,&last3);
break;
case2:
pushpro(&head,&head2,&last2);
break;
case1:
pushpro(&head,&head1,&last1);
break;
}
}
time++;
//从最高优先级摘下一个进程并执行
if(head3!
=NULL)
{running(&head3,&last3,&head2,&last2,time,fp,head3,head2,head1);
continue;
}
elseif(head2!
=NULL)
{running(&head2,&last2,&head1,&last1,time,fp,head3,head2,head1);
continue;
}
elseif(head1!
=NULL)
{running(&head1,&last1,&head1,&last1,time,fp,head3,head2,head1);
continue;
}
}
puts("进程调度信息已写入桌面上文件---pcb.txt中!
");
printf("NORMALTERMINATION!
\n");
fclose(fp);
return0;
}