模拟在单处理器多进程操作系统的CPU调度

来源:互联网 发布:铁路抢票软件 编辑:程序博客网 时间:2024/06/07 08:11

 模拟在单处理器多进程操作系统的CPU调度。本实验为模拟实验,不要求实现真正的进程创建与进程调度。主要实现各种调度算法。

进程PCB结构:标识符、进程名称、到达时间、服务时间、剩余运行时间、已使用时间、进程状态。其中进程状态有三种:就绪R,运行E,结束F。

剩余运行时间和已使用时间两个属性用于时间片轮转算法和多级反馈队列算法。进程每使用完一个时间片,已使用时间就会增加一个时间片的长度,剩余运行时间=服务时间 – 已使用时间。


仅完成了先来先服务算法的调度和短作业优先算法:

在linux中因缺少conio包无法运行,可自行修改后 就能运行。我在VC++软件中运行如下代码:

#include "stdio.h"#include<stdlib.h>#include<conio.h>#include<time.h>#include<string.h>#include <iostream.h>#define getpch(type) (type*)malloc(sizeof(type))typedef struct pcb PCB;//定义进程控制块的PDBstruct pcb{int id; //标识符char name[10];//名称int time_start;//到达时间int time_need;//服务时间int time_left;//剩余运行时间int time_used;//已使用的CPU时间char state;//进程状态};//系统函数//停顿几秒void _sleep(int n){clock_t goal;goal = (clock_t)n * CLOCKS_PER_SEC + clock();while(goal>clock());}//按任意键继续char _keygo(){char c;printf("按任意键继续.......\n");c = getch();return c;}///////////////////////////用户函数/////////////////////////////数据设置区域int time_unit = 2;//时间片长度const maxnum = 10;//最大进程数量int num = 5;//实际进程数量PCB pcbdata[maxnum] = {{1000,"A",0,4,4,0,'R'},{1001,"B",2,5,3,0,'R'},{1002,"C",5,3,5,0,'R'},{1003,"D",4,2,2,0,'R'},{1004,"E",1,1,4,0,'R'},};//就绪队列,存放进程的pcbint ready[maxnum];//记录排序使用哪个数值作为排序对象int order[maxnum];//手工输入数据void input(){int i;printf("进程总数为:");scanf("%d",&num);for(i = 0; i< num; i++){//系统自动分配标识符pcbdata[i].id = 1000 + i;printf("输入第%d个进程名:",i+1);scanf("%s",&pcbdata[i].name);printf("输入第%d个进程达到时间:",i+1);scanf("%s",&pcbdata[i].time_start);printf("输入第%d个进程服务时间:",i+1);scanf("%s",&pcbdata[i].time_need);pcbdata[i].time_left = pcbdata[i].time_need;//剩余运行时间,初始值和服务时间相同printf("\n");pcbdata[i].time_used = 0;//已使用CPU时间初始值为0pcbdata[i].state = 'R';//进程初始状态为就绪R}}///////////////////////调度函数///////////////////////////////先来先服务算法void FCFS(){int i,j,temp;double k;for(i = 0;i < num; i++){order[i] = pcbdata[i].time_start;ready[i] = i;}//冒泡排序for(i = 0; i< num; i++){//按照到达时间大小排序for(j = i+1; j<num; j++){if(order[i] > order[i+1]){temp = order[i];order[i] = order[j];order[j] = temp;temp = ready[i];ready[i] = ready[j];ready[j] = temp;} }}printf("--先来先服务算法调度:非抢占,无时间片---\n");printf("\n");temp = pcbdata[ready[0]].time_start;for(i = 0; i < num; i++){printf("第%d个进程--%s,",i+1,pcbdata[ready[i]].name);printf("到达时间--%d,服务时间--%d\n",pcbdata[ready[i]].time_start,pcbdata[ready[i]].time_need);printf("本进程正在运行...........\n");_sleep(1);printf("运行完毕\n");temp += pcbdata[ready[i]].time_need;j = temp-pcbdata[ready[i]].time_start;k = (float)j/pcbdata[ready[i]].time_need;printf("完成时间--%d,周转时间--%d,带权周转时间--%.1f\n",temp,j,k);printf("\n");}printf("--------所有进程调度完毕------\n");}//短作业优先算法void SJF(){int i,j,temp,min,index,temp1;double k;for(i = 0;i < num; i++){order[i] = pcbdata[i].time_start;ready[i] = i;}//冒泡排序for(i = 0; i< num; i++){//按照到达时间大小排序for(j = i+1; j<num; j++){if(order[i] > order[i+1]){temp = order[i];order[i] = order[j];order[j] = temp;temp = ready[i];ready[i] = ready[j];ready[j] = temp;} }}temp = pcbdata[ready[0]].time_start;for(i=0;i<num-1;i++){//cout<<"ready[i]="<<ready[i]<<endl;temp =temp+ pcbdata[ready[i]].time_need;//完成时间min=999;for(j=i+1;j<num-1;j++){//cout<<"temp="<<temp<<endl;if(pcbdata[ready[j]].time_start < temp)//到达时间<完成时间{//cout<<pcbdata[ready[j]].time_start<<" "<<temp<<endl; if(pcbdata[ready[j]].time_need<min)//服务时间最小 { index=j;//记录下标 min=pcbdata[ready[j]].time_need; }}}//把服务时间最小的放到前面优先调度temp1 = ready[i+1];ready[i+1] = ready[index];ready[index] = temp1;}printf("--短作业优先算法调度:非抢占,无时间片---\n");printf("\n");temp = pcbdata[ready[0]].time_start;for(i = 0; i < num; i++){printf("第%d个进程--%s,",i+1,pcbdata[ready[i]].name);printf("到达时间--%d,服务时间--%d\n",pcbdata[ready[i]].time_start,pcbdata[ready[i]].time_need);printf("本进程正在运行...........\n");_sleep(1);printf("运行完毕\n");temp += pcbdata[ready[i]].time_need;j = temp-pcbdata[ready[i]].time_start;k = (float)j/pcbdata[ready[i]].time_need;printf("完成时间--%d,周转时间--%d,带权周转时间--%.1f\n",temp,j,k);printf("\n");}printf("--------所有进程调度完毕------\n");}//高相应比算法void HRF(){}//按照先来先服务并使用时间片轮转void Timeslice(){}//多级反馈调度队列,抢占式调度void MRLA(){}/////////主函数void main(){int i = 0, sch = 99;while(sch != 0){printf("\n请选择其中一种调度算法:\n");printf("(1)先来先服务FCFS\n");printf("(2)短作业优先SJF\n");printf("(3)高相应比HRF\n");printf("(4)时间片轮转Timeslice\n");printf("(5)多级反馈队列MRLA\n");printf("(0)退出\n");printf("请输入一个数字:");scanf("%d",&sch);switch (sch){case 1:FCFS();break;case 2: SJF();break;case 3:HRF();break;case 4:Timeslice();break;case 5:MRLA();break;case 0:printf("退出程序\n");;break;}}_keygo();}//////////////////一下函数主要用于程序调试跟踪//显示一个PCB的具体参数内容void dis_pcb(PCB *pr){printf("%s的PCB:\n",pr->name);printf("标识符--%d,状态--%c,到达时间--%d\n",pr->id,pr->state,pr->time_start);printf("服务时间--%d,剩余运行时间--%d,已用时间--%的\n",pr->time_need,pr->time_left,pr->time_used);printf("-------------------------\n");}//像是所有进程PCBvoid dis_pcb_all(){int i;printf("******当前所有进程状态*****\n");for(i = 0; i< num; i++)dis_pcb(&pcbdata[i]);}//显示就绪队列void dis_ready(){int i;printf("当前就绪队列为:\n");for(i = 0; i< num-1; i++)printf("%s--",pcbdata[order[i]].name);printf("%s\n",pcbdata[order[i]].name);}


先来先服务算法运行结果如图:




从运行结果可以看出,先到先服务算法是按照到达时间来调度的,到达时间从早到晚分别为:A(0)->B(1)->C(2)->D(3)->E(4)。


短作业优先算法运行结果如下:



短作业优先思想就是先按照到达时间排序,按照到达时间早晚获得第一个调度的进程,以及服务时间,完成时间=开始时间+服务时间。然后在后面几个进程中寻找开始时间在完成时间之前的进程,在这些进程中再找服务时间最短的进程作为第二个调度的进程,依次类推。

根据算法可以推出以下步骤:

首先第一个调度 的进程为A进程,因为到达时间最快。

                  然后计算A进程的完成时间为0+4=4

                  然后在BCDE进程中找到到达时间小于4的进程,分别为:B C D

                  然后在B C D进程中找到服务时间最小的:D进程,所以D进程为第二个调度进程。此时完成时间为4+2=6

                  继续在B C E进程中找到达时间小于6的进程,分别为:B C E

                  然后在B C E进程中找到服务时间最小的:B进程,所以B进程为第三个调度进程。此时完成时间为6+3=9

                  继续在C E进程中找到达时间小于9的进程,分别为C E

                  然后在C E进程中找到服务时间最小的 :E进程,所以E进程为第四个调度进程,C进程为最后一个调度进程。

 

从代码执行结果可看出算法正确。



原创粉丝点击