第3章处理机管理7.1实验内容处理机管理是操作系统中非常重要的部分。
为深入理解进程管理部分的功能,设计几个调度算法,模拟实现处理机的调度。
7.2实验目的在多道程序或多任务系统中,系统同时处于就绪状态的进程有若干个。
也就是说能运行的进程数远远大于处理机个数。
为了使系统中的各进程能有条不紊地运行,必须选择某种调度策略,以选择一进程占用处理机。
要求学生设计一个模拟单处理机调度的算法,以巩固和加深处理机调度的概念。
7.3实验题目7.3.1设计一个按先来先服务调度的算法提示(1)假设系统中有5个进程,每个进程由一个进程控制块(PCB)来标识。
进程控制块内容如图7-1所示。
进程名即进程标识。
链接指针:按照进程到达系统的时间将处于就绪状态的进程连接成一个就绪队列。
指针指出下一个到达进程的进程控制块首地址。
最后一个进程的链指针为NULL。
估计运行时间:可由设计者指定一个时间值。
达到时间:进程创建时的系统时间或由用户指定。
调度时,总是选择到达时间最早的进程。
进程状态:为简单起见,这里假定进程有两种状态:就绪和完成。
并假定进程一创建就处于就绪状态,用R表示。
当一个进程运行结束时,就将其置成完成状态,用C表示。
(2)设置一个队首指针head,用来指出最先进入系统的进程。
各就绪进程通过链接指针连在一起。
(3)处理机调度时总是选择队首指针指向的进程投入运行。
由于本实验是模拟实验,所以对被选中进程并不实际启动运行,而只是执行:估计运行时间减1用这个操作来模拟进程的一次运行,而且省去进程的现场保护和现场恢复工作。
(4)在所设计的程序中应有显示或打印语句,能显示或打印正运行进程的进程名,已运行是、还剩时间,就绪队列中的进程等。
所有进程运行完成是,给出各进程的周转时间和平均周转时间。
先来先服务(FCFS)调度算法/*源程序1.cpp,采用先来先无法法在Visual C++ 6.0下调试运行*//*数据结构定义及符号说明*/#include<iostream>#include<cstdio>#include<cmath>#include<cstring>using namespace std;enum STATUS {RUN,READY,WAIT,FINISH};struct PCBNode{int processID; //进程IDSTATUS status; //进程状态int reqTime; //总的需要运行时间int remainTime; //剩下需要运行时间int arriveTime; //进入就绪队列时间int startTime; //开始运行时间int finishTime; //结束运行时间int totalTime; //周转时间float weightTotalTime; //带权周转时间};struct QueueNode //队列结点结构{int ID; //进程IDstruct QueueNode * next; //队列中下一个进程指针};struct LinkQueue //队列结构{QueueNode *head;//队首};void Fcfs(LinkQueue& R, int& totalTimeSum, int& weightTotalTimeSum,PCBNode * ProcessTable);void InitialQueue(LinkQueue& R,PCBNode * ProcessTable,const int processnum);//初始化就绪队列Rvoid Input(PCBNode * ProcessTable, const int processnum);//从input.txt文件输入数据int main(){LinkQueue R; //就绪队列RR.head = NULL; //首地址为空const int processnum =5;//进程数为5int totalTimeSum = 0; //定义周转时间int WeightTotalTimeSum = 0;//定义带权周转时间PCBNode * ProcessTable=new PCBNode[processnum]; //建立进程表Input(ProcessTable, processnum); //输入进程表,进程数InitialQueue(R, ProcessTable, processnum); //初始队列Fcfs(R, totalTimeSum,WeightTotalTimeSum,ProcessTable); //定义为FCFS结构 cout<<"先来先服务的平均周转时间为:"<<totalTimeSum/processnum<<endl;cout<<"先来先服务的平均带权周转时间为:"<<WeightTotalTimeSum/processnum<<endl;//输出结果delete [] ProcessTable;//删除进程表return 0;}void Fcfs(LinkQueue& R, int& totalTimeSum, int& weightTotalTimeSum,PCBNode * ProcessTable)//初始化FCFS{totalTimeSum = 0;//初始化周转时间weightTotalTimeSum = 0;//初始化平均周转时间QueueNode* p;QueueNode* q;//队列结点p、qp = R.head->next;//头结点指向下一个结点为pif (p !=NULL ) //设p不为空{ProcessTable[p->ID].startTime = ProcessTable[p->ID].arriveTime;//进程表p进程开始时间=到达时间ProcessTable[p->ID].finishTime = ProcessTable[p->ID].arriveTime + ProcessTable[p->ID].reqTime;//进程表p进程结束时间=到达时间}for(q=p->next; q!=NULL; q=q->next)// for循环{if (ProcessTable[q->ID].arriveTime < ProcessTable[p->ID].finishTime)//如果进程表q进程到达时间<p进程结束时间{ProcessTable[q->ID].startTime = ProcessTable[p->ID].finishTime;//进程表q进程开始时间=p进程结束时间ProcessTable[q->ID].finishTime = ProcessTable[p->ID].finishTime+ProcessTable[q->ID].reqTime;//进程表q进程结束时间=p 进程结束时间+q进程总需要时间else{ProcessTable[q->ID].startTime = ProcessTable[q->ID].arriveTime;//进程表q进程开始时间=q进程到达时间ProcessTable[q->ID].finishTime = ProcessTable[q->ID].arriveTime+ProcessTable[q->ID].reqTime;//进程表q进程结束时间=q 进程到达时间+q进程总需要时间}p = q;}for(q=R.head->next; q!=NULL; q=q->next)//for循环{ProcessTable[q->ID].totalTime = ProcessTable[q->ID].finishTime - ProcessTable[q->ID].arriveTime;//进程表q周转时间=q进程结束时间-q进程到达时间 ProcessTable[q->ID].weightTotalTime = ProcessTable[q->ID].totalTime/ProcessTable[q->ID].reqTime; //进程表q带权周转时间=q进程周转时间/q进程总需时间totalTimeSum += ProcessTable[q->ID].totalTime;//周转总时间=q进程周转时间+总周转时间weightTotalTimeSum += ProcessTable[q->ID].weightTotalTime;//带权周转总时间=q进程带权周转时间+带权周转总时间}int t = 0;//定义时间tfor(q=R.head->next; q!=NULL; q=q->next)//for循环{cout<<"*********************"<<endl;//输出while ( t<ProcessTable[q->ID].finishTime )//当进程表q进程结束时间<T时 {cout<<"时刻"<<t<<": 进程"<<q->ID<<"活动"<<endl;//输出时间和进程ID t++;}if (q->next != NULL)//设q指向的下个结点不为空{cout<<"时刻"<<t<<": 进程"<<q->ID<<"结束活动,开始下一个进程."<<endl;//输出cout<<"进程"<<q->ID<<"的周转时间为: "<<ProcessTable[q->ID].totalTime<<endl;//输出周转时间cout<<"进程"<<q->ID<<"的带权周转时间为: "<<ProcessTable[q->ID].weightTotalTime<<endl<<endl;//输出带权周转时间 }elsecout<<"时刻"<<t<<": 进程"<<q->ID<<"结束活动."<<endl<<endl;//输出 cout<<"进程"<<q->ID<<"的周转时间为: "<<ProcessTable[q->ID].totalTime<<endl;//输出cout<<"进程"<<q->ID<<"的带权周转时间为: "<<ProcessTable[q->ID].weightTotalTime<<endl<<endl; //输出}}cout<<"所有进程结束活动."<<endl<<endl;//输出p = R.head;//头结点为pfor(q=p->next; q!=NULL; q=q->next)//for循环{delete p;//删除pp = q;}}void InitialQueue(LinkQueue& R, PCBNode * ProcessTable,const int processnum) {for (int i=0;i<processnum;i++)//for循环,定义i为进程数{ProcessTable[i].processID=i;//进程表ID号与i对应ProcessTable[i].reqTime=ProcessTable[i].remainTime;//进程表所总需要时间=进程表剩下需要时间ProcessTable[i].finishTime=0;//完成时间ProcessTable[i].startTime=0;//开始时间ProcessTable[i].status=WAIT;//进程状态为等待ProcessTable[i].totalTime=0;//周转时间ProcessTable[i].weightTotalTime=0;//带权周转时间}R.head = new QueueNode;//头指针为新结点R.head->next = NULL;//头指针指向为空QueueNode * p;QueueNode * q;//定义结点q,pfor (i=0;i<processnum;i++)//for循环{p = new QueueNode;//p为新结点p->ID = i;//p的ID号与i对应p->next = NULL;//p指向空if (i == 0)//设i为0{R.head->next = p;//头指针指向p}elseq->next = p;//q指向pq = p;}}void Input(PCBNode * ProcessTable, const int processnum){FILE *fp; //读入进程的相关内容if((fp=fopen("input.txt","r"))==NULL)//设input.txt文件为空{cout<<"can not open file!"<<endl;//输出exit(0);}for(int i=0;i<processnum;i++)//for循环{fscanf(fp,"%d %d %d",&ProcessTable[i].arriveTime,&ProcessTable[i].remainTime);//扫描进程到达时间,还剩需要时间}fclose(fp);}或者改进,要做到没有错误,有一定的难度。