处理机调度算法实验报告
操作系统进程调度实验报告
一.实验目的
用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的解.
进程调度时进程管理的主要内容之一,通过设计,编制,调试一个简单的进程调度模拟系统,对进程调度,进程运行状态变换加深理解和掌握。模拟计算机操作系统的进程调度,建立进程控制块PCB,要包含有关进程的描述信息,控制信息以及资源信息.模拟系统根据PCB感知进程的存在和通过PCB中所包含的各项变量的变化,掌握进程所处的状态以达到控制进程活动的目的.要实现进程的状态及其转换,进程的创建与撤消,进程的阻塞与唤醒.用P,V原语操作实现进程互斥.
二.实验要求
建立进程控制块PCB,用PCB实现进程在运行过程中的一切状态,未创建、就绪、运行、等待、退出.以完成资源的共享,实现进程的同步与互斥.程序要求用p,v操作实现进程互斥.
三.实验平台
Windows XP 下的Microsoft vitual c++平台
四.所用语言
Microsoft Visual C++语言
五.机器要求
Microsoft Windows XP Professional
版本 2002
Service Pack
256MB内存
SVGA(800×600分辨率,256色或更高级的显示卡
鼠标或其他相容设备
六.系统分析
设计建立四个进程,模拟模拟批处理多道操作系统的进程调度,
进程调度算法,采用最高优先数优先的调度算法.每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。进程的运行时间以时间片为单位进行计算。每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。
同时,以上操作执行完了以后,要反映出在这个操作过程中p原语和v原语操作的执行情况,于是调用预先创建的函数.并输出p,v操作在整个程序过程中的执行情况和状态.于是我们创建四个进程process1,process2,process3,process4具体反应p,v原语对四个进程的操作.要预先说明的是,在四个进程并不是与输入的四个进程一一对应.输入的四个进程要按照优先级的高低来确定它们执行的顺序,优先级从高到低顺序执行,所以创建的process1到process4四个进程函数与输入的四个进程的执行顺序是一一对应的,也就是说,优先级最高的与process1对应,依次下来.这样我们创建的四个进程函数才能正确反映p,v原语对四个具体进程的操作过程.
过程运行中除了调用P操作申请信号量外,还要调用V操作释放信号量,V操作在释放信号量之后,还将唤醒因申请此信号量而被阻塞的过程。
在程序运行的四个过程(PROCESS1,PROCESS2,PROCESS3,PROCESS4),其中过程运行中通过P操作申请信号量1,过程2通过V操作释放信号量2,然后做一次操作申请信号量2。四个过程的运行通过进程调度模块同意安排,调度模块通过FIND()函数找到第一个就绪过程,如果当前没有过程已在运行,就直接运行此过程,如果有,则比较两者的优先数,然后运行优先权高者。
七.系统功能
因为没有设计动化效果,所以没有对系统功能详细说明.只是输出/输入语句.
八.数据结构
进程控制块1PCB
struct{
int id;
char status;
int priority;
int waiter1;
}pcb[5];
信号量
struct{
int value;
int waiter2;
}sem[4];
现场保护栈stack
char stack[11][4]
每个进程都有一个大小为10个字的现场保护栈,用来保护被中断时的断点地址等信息。
全局变量
int i; 用以模拟一个通用寄存器
char addr; 用以模拟程序计数器
int m1,m2;为系统设置的公用数据被三个进程共享使用
定义进程控制块2PCB
struct pcb {
char name[10];
char state;
int super;
int ntime;
int rtime;
struct pcb* link;
}*ready=NULL,*p;
现场保护栈:
char stack[11][5]
每个进程都有一个大小为11个字的现场保护栈,用来保护被中断时的断点地址等信息.
全局变量
int i; 用以模拟一个通用寄存器
char addr; 用以模拟程序计数器
int m1,m2;为系统设置的公用数据被四个进程共享使用.
int num;确定进程数量
struct{
int id; //进程标号
int waiter1; //指针,用于标识等待队列的下一个进程
int priority; //进程优先级
char status; //进程状态
}Pcb[5];进程控制快Pcb
九.分工情况
在我们小组合作的过程中,由我们三个人共同完成,具体的分工是这样的:
框图设计和编写程序代码由许向前和申友明共同完成,因为框图和程序紧密相连.
整个幻灯片设计是由杨毅完成
十.讨论情况
第一次讨论
时间:2005 11 1 地点:12栋116寝室
主持:申友明
内容:讨论这次作业的合作和分工情况,并认真阅读老师给的辅助资料.
第二次讨论
时间:2005 11 10 地点:12栋116寝室
主持:杨毅
内容:一起参阅了一些相关的资料和源代码,并构建整个作业的大约流程图.
第三次讨论
时间:2005 11 17 地点:12栋116寝室
主持:许向前
内容:具体完成了分工操作,并将我们完成的部分集中在一起,反复修改,由杨毅负责的整个课件基本形成.
最后一次讨论是在
对我们所努力产生的成果从总体上进行包装.作业完成.
十一.流程图
流程图一.
流程图二.
流程图三
流程图四
流程图五
流程图六
流程图七
流程图八
流程图九
流程图十
十一.程序代码
#include
#include "iostream.h"
#include
#define num 4
#include
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
int m1; //共享变量
int m2; //共享变量
struct{
int id; //进程标号
int waiter1; //指针,用于标识等待队列的下一个进程
int priority; //进程优先级
char status; //进程状态
}Pcb[5];
struct{
int value; //信号量的值
int waiter2; //指针,用于标识等待此信号量队列的第一个进程
}sem[4];
char stack[11][5]; //现场保护堆栈
int i; //cpu中的通用寄存器
int ep; //当前运行进程指针
char addr; //程序运行时的地址
void init(); //初始化
int find(); //找出就绪进程
int w2(); //
int process1(); //进程1
int process2(); //进程2
int process3(); //进程3
int process4(); //进程4
int P(int,int ,char); //P原语
int V(int,int ,char); //V原语
//**************************************************
struct pcb { /* 定义进程控制块PCB */
char name[10];
char state;//状态
int super;//最先判别优先级
int waittime;//等待时间
int xtime;
int ntime;
int rtime;
struct pcb* link;
}*ready=NULL,*p,*t=NULL;
typedef struct pcb PCB;
//*************************************
void init() //初始化进程
{
int j,k;
Pcb[0].status='w'; //进程状态设置为等待
Pcb[0].priority=5; //进程的优先级别
for(j=1;j<=4;j++)
{
Pcb[j].id=j; //进程编号
Pcb[j].status='r'; //进程状态设置为就绪
Pcb[j].waiter1=0; //进程指针初始化为0
Pcb[j].priority=j; //设置进程优先级
}
for(j=1;j<=3;j++)
{
sem[j].value=1; //信号量赋值为1
sem[j].waiter2=0; //等待信号量队列的初始化
}
i=0; //CPU通用寄存器初始化
ep=0; //
addr='0'; //程序运行地址
m1=0; //共享变量初始化
m2=0; //共享变量初始化\
for(j=1;j<=10;j++)
{
for(k=1;k<=4;k++)
stack[j][k]='0'; //现场保护堆栈初始化
}
}
int find()
{ //查找初始化变量
int j;
for(j=1;j<=4;j++)
if(Pcb[j].status=='r')
return(j); //如果pcb队列中有就绪进程,返回进程编号
return(0);
}
int w2()
{ //进程调度程序
int pd;
pd=find(); //找出就绪进程编号
if(pd==0)
return(0); //如果没有找到就绪进程,退出程序
else if(ep==0)
{ //如果当前运行进程是否为0
Pcb[pd].status='e'; //直接将当前进程设置为运行状态
ep=pd; //当前运行进程设置为pd
printf("进程%d正在执行\n",ep);
}
else
if(Pcb[pd].priority如果当前进程比待调入进程优先级进行比较
{//调入进程优先级别高
Pcb[ep].status='r'; //把CPU运行进程执行状态设置为就绪
printf("读取进程%d\n",Pcb[pd].id);
Pcb[pd].status='e'; //将待调入进程执行状态设置为执行
ep=pd; //将当前运行进程指针为待调入进程
}
printf("运行进程%d\n",ep);
i=stack[1][ep]; //恢复进程的通用寄存器中的值和运行地址。
addr=stack[2][ep];
switch(ep)
{ //根据当前运行的进程选择运行
case 1:process1();
break;
case 2:process2();
break;
case 3:process3();
break;
case 4:process4();
break;
default:printf("当前进程出现错误%d\n",ep);
break;
}
}
int process1()
{//进程1
if(addr=='m')
goto m; //如果当前运行地址是m,跳到m运行
i=1;
a:
printf("进程1在信号量sem[1]上调用P操作\n");
if(P(1,1,'m')==0) return(0); //进行p操作,m表示程序执行到m
else goto m;
m:
printf("打印进程1...m1=%d\n",m1); //进程1的操作,打印,寄存器i+5
printf("打印进程1...i=%d\n",i);
i+=5;
goto a; //跳回a执行
}
int process2()
{//进程分为4部分
if(addr=='m') goto m;
if(addr=='n') goto n;
i=1;
a:
printf("进程2在信号量sem[2]上调用P操作\n");
if(P(2,2,'m')==0) return(0);
m:
m1=2*m2;
printf("进程2在信号量sem[1]上调用V操作m1=%d\n",m1);
if(V(1,2,'n')==0) return(0);
else{
n:
printf("打印进程2...i=%d\n",i);
i+=10;
goto a;
}
}
int process3()
{
if(addr=='m') goto m;
if(addr=='n') goto n;
i=1;
a:
//if(i>4){
printf("进程3在信号量sem[3]上调用P操作\n");
if(P(3,3,'m')==0) return(0);
// }
m:
m1=3*m2;
printf("进程3在sem[2]信号量上调用V操作m=%d\n",m2);
if(V(2,3,'n')==0) return(0);
else{
n:
printf("打印进程3...i=%d\n",i);
i+=15;
goto a;
}
}
int process4()
{
if(addr=='m') goto m;
if(addr=='n') goto n;
i=1;
a:
if(i>4){
printf("进程4在信号量sem[3]上调用P操作\n");
if(P(3,4,'n')==0) return(0);
}
n:
m2=i;
printf("进程4在sem[3]信号量上调用V操作m=%d\n",m2);
if(V(3,4,'m')==0) return(0);
else{
m:
printf("打印进程4...i=%d\n",i);
i+=1;
goto a;
}
}
int P(int se,int P,char ad)//p操作
{
int w;
sem[se].value--; //信号量减1
if(sem[se].value==0) return(1); //如果信号量=0,返回1,说明阻塞
printf("阻塞当前进程%d\n",P);
Pcb[P].status='w'; //改变进程状态
ep=0; //运行进程为空
Pcb[P].waiter1=0; //设为尾末
w=sem[se].waiter2; //找出等待队列的队尾
if(w==0) sem[se].waiter2=P; //插入等待队列
else{
while(Pcb[w].waiter1!=0) w=Pcb[w].waiter1;
Pcb[w].waiter1=P;
}
stack[1][P]=i; //保存现场
stack[2][P]=ad;
return(0);
}
int V(int se,int P,char ad)//v操作
{
int w;
sem[se].value++; //信号量加1
if(sem[se].value>0) return(1); //信号量>0,无等待进程
w=sem[se].waiter2; //返回第一个等待进程
sem[se].waiter2=Pcb[w].waiter1; //调整位置
Pcb[w].status='r'; //进程改变状态
printf("唤醒进程%d\n",w);
stack[1][P]=i; //进程状态进栈
stack[2][P]=ad;
return(0);
}
sort() /* 建立对进程进行优先级排列函数*/
{
PCB *first, *second;
int insert=0;
if((ready==NULL)||((p->super)>(ready->super)))
/*优先级最大者,插入队首*/
{
p->link=ready;
ready=p;
}
else /* 进程比较优先级,插入适当的位置中*/
{
first=ready;
second=first->link;
while(second!=NULL)
{
if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/
{ /*插入到当前进程前面*/
p->link=second;
first->link=p;
second=NULL;
insert=1;
}
else /* 插入进程优先数最低,则插入到队尾*/
{
first=first->link;
second=second->link;
}
}
if(insert==0)
first->link=p;
}
}
sort1()
{
p->link=t;
ready=p;
}
input() /* 建立进程控制块函数*/
{
int i;
//clrscr(); /*清屏*/
//printf("\n 请输入进程号:");
//scanf("%d",&num);
for(i=0;i
{
printf("\n 进程号No.%d:\n",i);
p=getpch(PCB);
printf("\n 输入进程名(字符/字符串):");
scanf("%s",p->name);
printf("\n 输入进程优先数:");
scanf("%d",&p->super);
printf("\n阻塞进程的时间片 :");
scanf("%d",&p->waittime);
printf("\n 进程要运行的时间:");
scanf("%d",&p->ntime);
printf("\n阻塞时间:");
scanf("%d",&p->xtime);
printf("\n");
p->rtime=0;
p->state='w';
p->link=NULL;
sort(); /* 调用sort函数*/
}
}
int space()
{
int l=0;
PCB* pr=ready;
while(pr!=NULL)
{
l++;
pr=pr->link;
}
return(l);
}
disp(PCB * pr) /*建立进程显示函数,用于显示当前进程*/
{
printf("\n qname \t state \t waittime \t ndtime \t runtime \t xtime\n");
printf("%s\t",pr->name); printf(" ");
printf("%c\t",pr->state); printf(" ");
printf("%d\t",pr->waittime);printf(" ");
printf("%d\t",pr->xtime); printf(" ");
printf("%d\t",pr->ntime); printf(" ");
printf("%d\t",pr->rtime);printf(" ");
printf("\n");
}
check() /* 建立进程查看函数 */
{
PCB* pr;
PCB* pp;
printf("\n**********当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/
disp(p);
pr=ready;
printf("\n***********当前就绪队列状态为:\n"); /*显示就绪队列状态*/
while(pr!=NULL)
{
disp(pr);
pr=pr->link;
}
pp=t;
printf("\n阻塞队列状态为:\n");
while(pp!=NULL)
{
disp(pp);
pp=pp->link;
disp(pr);
pr=pr->link;
}
}
destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/
{
printf("\n 进程 [%s] 已完成.\n",p->name);
free(p);
}
running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/
{
PCB *ptr;
while(p->rtime!=p->ntime)
{
p->rtime++;
printf("\n当前所运行的进程状态为:");
disp(p);
ptr=t;
while(ptr!=NULL)
{
ptr->xtime--;
if(ptr->xtime==0)
{
p=ptr;
sort();
}
ptr->link=ptr;
}
if(p->rtime==p->waittime)
{
printf("\n该进程被阻塞:");
sort1();
break;}
}
if(p->rtime==p->ntime)
destroy();
}
//**
main()
{
//******************************************
int len,h=0;
char ch;
cout<<"输入四个进程的相关数据:"<
cout<<"***************************************************************"<
input(); //函数调用
len=space();
printf("%d",len);
while((len!=0)&&(ready!=NULL))
{
ch=getchar();
h++;
printf("\n The execute number:%d \n",h);
p=ready;
ready=p->link;
p->link=NULL;
p->state='R';
check();
running();
printf("\n ");
printf("\n 按任一键继续......");
ch=getchar();
}
printf("\n\n 进程已经完成.\n");
cout<<"******************************************************"<
ch=getchar();
//*****************************************************
init(); //调用该函数
cout<<"现在输出四个进程的p,v操作的具体执行情况"<
cout<<"**********************************************"<
printf("系统程序开始执行\n");
for(;;)
{
if(find()!=0) //找出就绪进程
w2(); //进程调度
else break;//退出程序
}
printf("系统程序结束\n");
cout<<"***********************************************"<
cout<<"冰☆☆snow小组设计"<
}
//**************
运行示列
十三.实验小结
操作系统是计算机系统中必不可少的系统软件。它是计算机系统中各种资源的管理者和各种活动的组织者、指挥者。操作系统采用时间片法调度进程,使系统资源得到充分的利用,用户也可以花更少的时间完成更多的工作,这次模拟系统调度进程,让我们明白了系统时间片的调度方法和p,v原语操作情况,对操作系统理论的学习更加深一层.同时,这是我们小组共同努力的结果,团体合作的精神是很可贵的.
这次作业具有深远的意义.
一实验内容按优先数调度算法实现处理器调度二实验目的在采用多道程序设计的系统中往往有若干个进程同时处于就绪状态当就绪进程个数大于处理…
中南大学实验名称处理机调度课程名称计算机操作系统学生姓名盛希玲学号0903060215学院信息科学与工程学院专业班级电子信息工程0…
操作系统实验报告处理机调度一设计目的功能与要求设计目的掌握处理机调度的相关内容对进程调度算法有深入的理解实验内容模拟实现进程调度功…
深圳大学实验报告课程名称:操作系统实验项目名称:处理机调度学院:计算机与软件学院专业:软件工程指导教师:报告人:学号:班级:实验时…
河南科技大学实验报告课程名称计算机操作系统题目进程控制与处理机调度综合实验院系国际教育学院班级学号学生姓名指导教师邱涌日期20xx…
目录1课程设计目的32课程设计要求33相关知识34需求分析45概要设计56详细设计67测试修改及运行结果138参考文献159结束语…
天津大学仁爱学院实验类型实验名称实验地点学生姓名班级操作系统实验报告必修实验日期20xx年4月18日进程调度二实验楼504李帅帅指…
操作系统实验报告单说明仅作参考请勿雷同一实验目的在采用多道程序设计的系统中往往有若干个进程同时处于就绪状态当就绪进程个数大于处理器…
一实验内容按优先数调度算法实现处理器调度二实验目的在采用多道程序设计的系统中往往有若干个进程同时处于就绪状态当就绪进程个数大于处理…
中南大学实验名称处理机调度课程名称计算机操作系统学生姓名盛希玲学号0903060215学院信息科学与工程学院专业班级电子信息工程0…