在多道程序环境下,主存中有着多个进程,其数目往往多过于处理机数目。这就要求系统能按某种算法,动态的把处理机分配给就绪队列中的一个进程,使之执行。在OS中的调度的实质是一种资源分配,因而调度算法是指:根据系统的资源分配策略所规定的资源分配算法。对于不同的系统和系统目标,通常采用不同的调度算法,目前存在的多种调度算法中,有的算法适用于作业电镀,有的算法适用于进程调度;但也有些调度算法即可用于作业调度,也可用于进程调度。多级反馈队列调度算法是一种CPU处理机调度算法,它不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。多级反馈队列调度算法的思想设置多个就绪队列,并为各个队列赋予不同的优先级和不同长度的时间片;第一个队列的优先级最高,进程所执行时间片最小。新创建的进程挂到第一优先级的队列后,然后按FCFS原则排队等待调度。当轮到其执行时,如它能在时间片内完成,便撤离系统;如果不能完成,便被挂入第二级队列后,……;仅当第一级队列空闲时,调度程序才调度第二级队列中的进程运行,依次类推……;新进程可抢占低级进程的处理机。多级(假设为N级)反馈队列调度算法可以如下原理:1、设有N个队列(Q1,Q2....QN),其中各个队列对于处理机的优先级是不一样的,也就是说位于各个队列中的作业(进程)的优先级也是不一样的。一般来说,优先级Priority(Q1)Priority(Q2)...Priority(QN)。怎么讲,位于Q1中的任何一个作业(进程)都要比Q2中的任何一个作业(进程)相对于CPU的优先级要高(也就是说,Q1中的作业一定要比Q2中的作业先被处理机调度),依次类推其它的队列。2、对于某个特定的队列来说,里面是遵循时间片轮转法。也就是说,位于队列Q2中有N个作业,它们的运行时间是通过Q2这个队列所设定的时间片来确定的(为了便于理解,我们也可以认为特定队列中的作业的优先级是按照FCFS来调度的)。3、各个队列的时间片是一样的吗?不一样,这就是该算法设计的精妙之处。各个队列的时间片是随着优先级的增加而减少的,也就是说,优先级越高的队列中它的时间片就越短。同时,为了便于那些超大作业的完成,最后一个队列QN(优先级最低的队列)的时间片一般很大(不需要考虑这个问题)。多级反馈队列调度算法描述:1、进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。2、首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。例如:Q1,Q2,Q3三个队列,只有在Q1中没有进程等待时才去调度Q2,同理,只有Q1,Q2都为空时才会去调度Q3。3、对于同一个队列中的各个进程,按照时间片轮转法调度。比如Q1队列的时间片为N,那么Q1中的作业在经历了N个时间片后若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列,直至完成。4、在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业(抢占式)。我们来看一下该算法是如何运作的:假设系统中有3个反馈队列Q1,Q2,Q3,时间片分别为2,4,8。现在有3个作业J1,J2,J3分别在时间0,1,3时刻到达。而它们所需要的CPU时间分别是3,2,1个时间片。1、时刻0J1到达。于是进入到队列1,运行1个时间片,时间片还未到,此时J2到达。2、时刻1J2到达。由于时间片仍然由J1掌控,于是等待。J1在运行了1个时间片后,已经完成了在Q1中的2个时间片的限制,于是J1置于Q2等待被调度。现在处理机分配给J2。3、时刻2J1进入Q2等待调度,J2获得CPU开始运行。4、时刻3J3到达,由于J2的时间片未到,故J3在Q1等待调度,J1也在Q2等待调度。5、时刻4J2处理完成,由于J3,J1都在等待调度,但是J3所在的队列比J1所在的队列的优先级要高,于是J3被调度,J1继续在Q2等待。6、时刻5J3经过1个时间片,完成。7、时刻6由于Q1已经空闲,于是开始调度Q2中的作业,则J1得到处理器开始运行。8、时刻7J1再经过一个时间片,完成了任务。于是整个调度过程结束。从上面的例子看,在多级反馈队列中,后进的作业不一定慢完成。FCFS、SJF和优先级调度算法仅对某一类作业有利,相比之下,它能全面满足不同类型作业的需求,较好实现公平性与资源利用率之间的平衡。对交互型作业,由于通常较短,这些作业在第一队列规定的时间片内完成,可使用户感到满意;对短批作业,开始时在第一队列中执行一个时间片就可完成,便可与交互型作业一样获得快速晌应,否则通常也仅需在第二、第三队列中各执行一个时间片即可完成,其周转时间仍较短;对长批作业,它们依次在第一至第n个队列中轮番执行,不必担心长时间得不到处理。多级队列调度算法的性能终端型用户:由于终端型用户所提交的作业大多属于交互型作业,作业通常都比较小,系统只要能够使这些作业在第一队列所规定的时间片内完成,便可以使终端型用户感到满意。短批处理作业用户:对于很短的批处理型作业,开始时象终端型作业一样,如果仅在第一队列中执行一个时间片即可完成,便可以获得与终端型作业一样的响应时间。对于稍长的作业,通常也只需要在第二队列和第三队列各执行一个时间片即可完成,周转时间还是比较短。长批处理作业用户:对于长作业,他将依次在n个队列中运行,然后按照轮转的方法运行,用户不必担心其作业长期得不到处理。多级反馈队列调度实现思想允许进程在队列之间移动。在系统中设置多个就绪队列,每个队列对应一个优先级,第一个队列的优先级最高,第二队列次之。以下各队列的优先级逐步低。各就绪队列中的进程的运行时间片不同,高优先级队列的时间片小,低优先级队列的时间片大。进程并非总是固定在某一队列中,新进程进入系统后,被存放在第一个队列的末尾。如果某个进程在规定的时间片内没有完成工作,则把它转入到下一个队列的末尾,直至进入最后一个队列。系统先运行第一个队列中的进程。当第一队列为空时,才运行第二个队列中的进程。依此类推,仅当前面所有的队列都为空时,才运行最后一个队列中的进程。当处理器正在第i个队列中为某个进程服务时,又有新进程进入优先级最高的队列(第1—(i-1)中的任何一个对列),则此新进程要抢占正在运行进程的处理器,即由调度程序把正在运行的进程放回第i队列的末尾,把处理器分配给新到的高优先级进程。除最低优先权队列外的所有其他队列,均采用相同的进程调度算法,即按时间片轮转的FIFO(先进先出)算法。最后一个队列中的进程按按时间片轮转或FCFS策略进行调度。它是综合了FIFO、RR和剥夺式HPF的一种进程调度算法#includestdio.h#includestdlib.h#defineM3//队列总数#defineN5//进程总数typedefstructpcb{intid;//进程号intintime;//提交时间intpriority;//优先级intstarttime;//开始执行时间intlength;//进程长度大小intendtime;//结束时间charstate;//状态intptime;//时间片structpcb*next;}*PCB,pcb;//进程控制块PCBCreatReady(PCBR,inti){R=(PCB)malloc(sizeof(pcb));R-id=i+1;R-priority=5-i;R-ptime=i+1;R-state='R';R-next=NULL;printf(第%d级:\t%d\t%d\n,R-id,R-priority,R-ptime);returnR;}PCBCreatWait(PCBW){inti;pcb*p,*q;q=W;printf(给进程初始化如下(tab键隔开):\n);printf(进程\tin时间\t优先级\t长度\n);for(i=0;iN;i++){p=(PCB)malloc(sizeof(pcb));p-next=NULL;p-id=i+1;printf(P%d\t,p-id);scanf(%d\t%d\t%d,&p-intime,&p-priority,&p-length);q-next=p;q=p;}returnW;}voidInsert(PCBR,pcb*cp){pcb*tail;tail=R;while(tail-next){tail=tail-next;}tail-next=cp;cp-next=NULL;}intFindQuery(PCBR[M]){inti,j;for(i=0;iM;i++){if(R[i]-next){j=i;break;}elseprintf(第%d级就绪队列为空\n,R[i]-id);}returnj;}intDispatch(PCBR,pcb*cp,PCBW,inttime,pcb*tp){ints;pcb*p,*phead;phead=W;p=W-next;cp-starttime=time;cp-length-=R-ptime;cp-endtime=cp-starttime+R-ptime;if(cp-length=0){s=1;//表示完成cp-endtime+=cp-length;}else{if(p){while(p){if((p-intimecp-endtime)&&(p-prioritycp-priority)){tp-id=p-id;tp-intime=p-intime;tp-length=p-length;tp-priority=p-priority;tp-state=p-state;//将抢占进程p备份到tp中phead-next=p-next;//从后备队列中删除抢占的进程cp-length+=cp-endtime-tp-intime;cp-endtime-=cp-endtime-tp-intime;s=-1;//表示被抢占break;}elseif(p-intime=cp-endtime){s=0;//在后备队列中没有可以抢占的进程时break;}p=p-next;phead=phead-next;}//查找可以抢占cpu的优先级高的进程tp}elses=0;//在后备队列没有进程时}returns;}voidPrint(PCBF){pcb*p;p=F-next;while(p){printf(P%d\t结束时间:%d\n,p-id,p-endtime);p=p-next;}}PCBMFQ(PCBW,PCBR[M],PCBF){pcb*cp;//当前系统操作的进程pcb*tp;//抢占cpu的进程tp=(PCB)malloc(sizeof(pcb));tp-priority=0;tp-next=NULL;inttime=0;//time表示系统当前时间intFinish=0;inti,have,j;ints;while(FinishN){cp=W-next;if(cp&&cp-intime=time){have=1;}elsehave=0;//判断当前时刻有无进程被提交if(have){i=0;W-next=cp-next;//从后备队列中删除cpInsert(R[0],cp);cp-priority=R[0]-priority;cp-state=R[0]-state;cp=R[0]-next;printf(%d时,P%d被提交入就绪队列%d\n,time,cp-id,R[0]-id);}//将新进程入第一级就绪队列else{i=FindQuery(R);//循环查找不为空的就绪队列cp=R[i]-next;printf(%d时,无可以提交的进程,因此转到就绪队列%d执行P%d\n,time,R[i]-id,cp-id);}s=Dispatch(R[i]