1、“先来先服务”调度算法 编程思路: 对各进程按照到达时间进行排序,挑选最先到达的进程一次性执行完毕,判断是否所有进程都被调度,若是则结束,否则返回挑选最先到达的进程一次性执行完毕步骤,继续执行后续程序。按照进程进入的先后次序来分配处理器。先进入就绪队列的进程优先被挑选,运行进程一旦占有处理器将一直运行下去,直到运行结束或者被阻塞,这是非抢占式调度。 代码如下:
//排序: 按照进程的arrivetime(从小到大)对pcb数组中的N个进程进行排序 void sort(pcb *p, int N) { for(int i=0; i < N-1; i++) { for(int j=0; j<N-1-i; j++) { if(p[j].arrivetime > p[j+1].arrivetime) { pcb temp; temp=p[j]; p[j]=p[j+1]; p[j+1]=temp; } } } } //运行 void run(pcb *p, int N) { int k; for(k=0; k<N; k++) { if(k==0) //第1个进程 { p[k].starttime = p[k].arrivetime; //第1个进程到达之后即可执行 p[k].finishtime = p[k].starttime + p[k].servicetime; } else { p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime; p[k].finishtime = p[k].starttime + p[k].servicetime; } } for(k=0; k<N; k++) { p[k].zztime = p[k].finishtime - p[k].arrivetime; p[k].dqzztime = p[k].zztime / p[k].servicetime; } } //显示 void Print(pcb*p, int N) { int k; printf("调用先来先服务算法以后进程运行的顺序是: "); printf("%s", p[0].name); //首先运行第一个进程p[0] for(k=1; k<N; k++) { printf("-->"); printf("%s", p[k].name); //输出 -->p[k].name } printf("\n"); printf("具体进程调度信息:\n"); printf("进程名 到达时间 服务时间 开始时间 结束时间 周转时间 带权周转时间\n"); for(k=0; k<N; k++) { printf("%4s", p[k].name); printf("%10.3f", p[k].arrivetime); printf("%10.3f", p[k].servicetime); printf("%10.3f", p[k].starttime); printf("%10.3f", p[k].finishtime); printf("%10.3f", p[k].zztime); printf("%10.3f\n", p[k].dqzztime); } } //先来先服务算法FCFS void FCFS(pcb *p,int N) { sort(p,N); run(p, N); Print(p, N); int k; float Attime = 0; //平均周转时间 float AQttime = 0; //平均带权周转时间 for(k=0; k<=N-1; k++) { Attime += p[k].zztime; AQttime += p[k].dqzztime; } Attime = Attime / N; AQttime = AQttime / N; printf("调用先来先服务算法的平均周转时间为:"); printf("%.3f\n", Attime); printf("调用先来先服务算法的平均带权周转时间为:"); printf("%.3f\n", AQttime); }运行结果 2、“短进程优先”调度算法 编程思路: 查找当前已经到达的最短进程,调用该进程,判断是否所有进程已经结束,若是则结束,否则,返回最初步骤继续运行。每次选出最短的进程进行调度,调度完毕则淘汰,直到所有进程都调度完毕。 代码如下:
//***优先级排序*** void sort(pcb *p, int N) { /* 1、对pcb型数组中的元素进行一个简单的排序,找到优先到达的进程 方便后续工作 */ //冒泡排序: N-1次循环,每次从p[0]到p[N-1-i]中找到最先到达的进程,放到p[N-1-i] //该循环结束就得到按照到达时间排序的结果 for(int i=0;i<N-1;i++) { //排序规则: 1、arrivetime越大,排序越往后 2、arrivetime相同时,servicetime短的优先 for(int j=0;j<N-1-i;j++) { if(p[j].arrivetime>p[j+1].arrivetime || (p[j].arrivetime==p[j+1].arrivetime && p[j].servicetime>p[j+1].servicetime) ) { //p[j+1]优先p[j]到达,交换p[j]和p[j+1] pcb temp; temp = p[j]; p[j] = p[j+1]; p[j+1] = temp; } } } /* 2、每个进程运行完成之后,找到当前时刻已经到达的最短进程 P[0]优先级最高,p[0].finishtime=p[0].arrivetime+p[0].servicetime m!=0时:p[m].finishtime=p[m-1].finishtime+p[m].servicetime 或: p[m].finishtime=p[m].arrivetime+p[m].servicetime(m-1进程执行完时,m进程还未到达) */ for(int m=0; m<N-1; m++) { if(m == 0) p[m].finishtime = p[m].arrivetime + p[m].servicetime; else p[m].finishtime = ((p[m-1].finishtime >= p[m].arrivetime)? p[m-1].finishtime: p[m].arrivetime) + p[m].servicetime; //(1)找到p[m].finishtime时刻哪些进程已经到达 int i=0; //i统计 p[m].finishtime时刻有几个进程已经到达 //从下一个进程p[m+1]开始寻找 for(int n = m+1; n <= N-1; n++) { if(p[n].arrivetime <= p[m].finishtime) i++; else break; /*由于在第1步已经对进程按照到达时间进行了排序 故:当p[n].arrivetime > p[m].finishtime时, 说明p[n]进程和其后面的其他进程都未到达。 不需再进行后续循环继续判断 */ } //(2)找到p[m].finishtime时刻已经到达的最短进程,当前进程为p[m] float min = p[m+1].servicetime; //next进程服务时间为p[m+1].servicetime (初值) int next = m+1; //next进程为m+1 (初值) //p[m+1]至p[m+i]这i个已到达进程中找到最短进程 for(int k = m+1; k < m+i; k++) //循环体每次判断为k+1,k+1为m+2 ~m+i,所以,k为m+1 ~ m+i-1 { //min的初值是p[m+1].servicetime, k+1为m+2 ~m+i if(p[k+1].servicetime < min) { min = p[k+1].servicetime; next = k+1; } } //(3)把最短进程放在p[m+1]进程处 pcb temp; temp=p[m+1]; p[m+1]=p[next]; p[next]=temp; } } //***运行*** void run(pcb *p, int N) { int k; //计算各进程的开始时间和结束时间 for(k=0; k < N; k++) { if(k==0) //第1个进程 { p[k].starttime = p[k].arrivetime; //第1个进程到达之后即可执行 p[k].finishtime = p[k].starttime + p[k].servicetime; } else { p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime; p[k].finishtime = p[k].starttime + p[k].servicetime; } } //计算各进程的周转时间和带权周转时间 for(k=0; k< N; k++) { p[k].zztime = p[k].finishtime - p[k].arrivetime; p[k].dqzztime = p[k].zztime / p[k].servicetime; } } //***显示*** void Print(pcb *p, int N) { int k; printf("调用最短进程优先算法以后进程运行的顺序是: "); printf("%s",p[0].name); for(k=1;k<N;k++) { printf("-->"); printf("%s", p[k].name); } printf("\n"); printf("具体进程调度信息:\n"); printf("进程名 到达时间 服务时间 开始时间 结束时间 周转时间 带权周转时间\n"); for(k=0; k<=N-1; k++) { printf("%4s", p[k].name); //%m.nf:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格 printf("%10.3f", p[k].arrivetime); printf("%10.3f", p[k].servicetime); printf("%10.3f", p[k].starttime); printf("%10.3f", p[k].finishtime); printf("%10.3f", p[k].zztime); printf("%10.3f\n", p[k].dqzztime); } } //***短进程优先*** void sjff(pcb *p,int N) { sort(p, N); run(p, N); Print(p, N); int k; float Attime = 0; // 平均周转时间 float AQttime = 0; //平均带权周转时间 for(k=0; k<=N-1; k++) { Attime += p[k].zztime; AQttime += p[k].dqzztime; } Attime = Attime/N; AQttime = AQttime/N; printf("调用短进程优先算法的平均周转时间为:"); printf("%.3f\n", Attime); printf("调用短进程优先算法的平均带权周转时间为:"); printf("%.3f\n", AQttime); }结果如下: 总结 先来先服务算法:是最简单的调度算法,既可以用于作业调度 ,也可以用于程序调度,当作业调度中采用该算法时,系统将按照作业到达的先后次序来进行调度,优先从后备队列中,选择一个或多个位于队列头部的作业,把他们调入内存,分配所需资源、创建进程,然后放入“就绪队列”,直到该进程运行到完成或发生某事件堵塞后,进程调度程序才将处理机分配给其他进程。 短进程优先算法:短进程优先算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。在把短作业优先调度算法用于作业调度时,它将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将它们调入内存运行。