精华内容
下载资源
问答
  • 操作系统 进程调度算法
  • 操作系统进程调度算法+代码+文档,很好用的
  • 操作系统 进程调度算法的设计,内附有代码
  • 计算机操作系统进程调度算法,有创建,撤销,增加资源,进程数,运行,等待的状态转化
  • 操作系统 进程调度算法 附实验结果 最高优先数优先
  • 操作系统进程调度算法C语言代码 本算法包含四种调度:先到先服务,短作业优先,时间片轮转,优先级优先!
  • 操作系统进程调度算法实现,可以直接运行的程序!!!!!!!!!!!
  • 常用的操作系统进程调度算法大致有:先来先服务调度算法,短进程优先调度算法,优先级调度算法(抢占式调度算法和非抢占式调度算法),基于时间片的轮转调度算法。 一、先来先服务和短作业(进程)优先调度算法 ...

    常用的操作系统进程调度算法大致有:先来先服务调度算法,短进程优先调度算法,优先级调度算法(抢占式调度算法和非抢占式调度算法),基于时间片的轮转调度算法。

    一、先来先服务和短作业(进程)优先调度算法

    1.先来先服务调度算法

    先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。

    2.短作业(进程)优先调度算法

    短作业(进程)优先调度算法SJ(P)F,是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。

    二、高优先权优先调度算法

    1.优先权调度算法的类型

    为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。

    1) 非抢占式优先权算法

    在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机重新分配给另一优先权最高的进程。这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。

    2) 抢占式优先权调度算法

    在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。因此,在采用这种调度算法时,是每当系统中出现一个新的就绪进程i 时,就将其优先权Pi与正在执行的进程j 的优先权Pj进行比较。如果Pi≤Pj,原进程Pj便继续执行;但如果是Pi>Pj,则立即停止Pj的执行,做进程切换,使i 进程投入执行。显然,这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。

    2.高响应比优先调度算法

    在批处理系统中,短作业优先算法是一种比较好的算法,其主要的不足之处是长作业的运行得不到保证。如果我们能为每个作业引入前面所述的动态优先权,并使作业的优先级随着等待时间的增加而以速率a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为:
    操作系统
    由于等待时间与服务时间之和就是系统对该作业的响应时间,故该优先权又相当于响应比RP。据此,又可表示为:
    操作系统
    由上式可以看出:

    (1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。

    (2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。

    (3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高,从而也可获得处理机。简言之,该算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期得不到服务。因此,该算法实现了一种较好的折衷。当然,在利用该算法时,每要进行调度之前,都须先做响应比的计算,这会增加系统开销。

    三、基于时间片的轮转调度算法

    1.时间片轮转法

    1) 基本原理

    在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几ms 到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。换言之,系统能在给定的时间内响应所有用户的请求。

    2.多级反馈队列调度算法

    前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程,而且如果并未指明进程的长度,则短进程优先和基于进程长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。

    (1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。

    (2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第队列便采取按时间片轮转的方式运行。

    (3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。



    展开全文
  • 操作系统进程调度算法(c语言实现)

    万次阅读 多人点赞 2019-12-03 17:15:00
    进程调度算法 一、先来先服务(FCFS) 基本思想:先到达的进程先进入就绪队列,先进行调度的原则。非抢占方式。 二、短作业优先(SJF) 基本思想:根据进程中的执行时间,选取执行时间最短的作业优先调度;可有抢占...

    进程调度算法

    一、先来先服务(FCFS)
    基本思想:先到达的进程先进入就绪队列,先进行调度的原则。非抢占方式。
    二、短作业优先(SJF)
    基本思想:根据进程中的执行时间,选取执行时间最短的作业优先调度;可有抢占或非抢占方式。
    三、优先权高者优先(HPF)
    基本思想:系统根据作业的优先权进行作业调度,每次选取优先权高的作业优先调度。作业的优先权通常用一个整数表示,也叫做优先数。可有抢占或非抢占方式。
    四、时间片轮转(RR)
    基本思想:系统将所有的就绪进程按先来先服务的原则,排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。时间片结束之后,将该进程加到就绪队列队尾;然后再把处理机分配给就绪队列中新的首进程。

    各程序的实现算法

    (1)FCFS先来先服务
    算法思想:①首先将输入的进程放入一个进程数组中,然后根据进程的到达时间进行排序(冒泡排序)。将最先到达的进程放入进程就绪队列中。②当队列不空时,从队头取出一个进程来执行,直至此进程执行完,并将在此进程执行期间到达的进程依次加入进程就绪队列。③如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    void FCFS(program pro[],int num){
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);    //按照到达顺序排序 
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue)); 
    	Queueinit(queue);   //初始化进程就绪队列
    	EnterQueue(queue,&pro[0]);   //将第一个进程放入队列
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前已进入的进程 
    	float sum_T_time = 0,sum_QT_time = 0 ; 
    	while(queue->size>0){    //当队列不为空
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)      //如果此进程的进入时间大于此时的时间,需要将时间转换到此进程的到达时间
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;  //记录完成时间
    		int T_time = done_time - curpro->enter_time;  //记录周转时间
    		sum_T_time += T_time;    
    		float QT_time = T_time / (curpro->running_time+0.0) ; //记录带权周转
    		sum_QT_time += QT_time;
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    		
    			if(tt>=pro[pronum].enter_time){   //程序执行时有程序到达则进入程序队列
    				EnterQueue(queue,&pro[pronum]);
    				pronum++;
    			}
    		}
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time,T_time,QT_time); //输出结果
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    }
    

    (2)短作业优先(SJF)
    算法思想:①首先也是按进程的到达时间进行排序。让最先到达的进程入队。②当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。③将这些到达的进程进行排序,按照进程服务时间的大小。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)④此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    void SJF(program pro[],int num) {
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	EnterQueue(queue,&pro[0]);   //第一个进程入队
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前的进程 
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		float QT_time = T_time / (curpro->running_time+0.0) ;
    		sum_T_time += T_time;
    		sum_QT_time += QT_time;
    		int pre = pronum;  //记录此进程执行期间第一个到达的进程的位置
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pronum++;
    			}
    		}
    		sortWithLongth(pro,pre,pronum);//将到达的进程按照服务时间排序
    		for(int i=pre;i<pronum;i++){    //到达的进程入队进程链入队列 
    			EnterQueue(queue,&pro[i]);
    		}
    		pre = pronum;
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time,T_time,QT_time);
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/num);
    }
    

    (3)优先权高者优先(HPF)
    算法思想:①首先也是按进程的到达时间进行排序。让最先到达的进程入队。②当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。③将这些到达的进程进行排序,按照进程优先权排序(权值小的先入)。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)④此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    void HPF(program pro[],int num){
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	EnterQueue(queue,&pro[0]);
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前的进程 
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		float QT_time = T_time / (curpro->running_time+0.0) ;
    		sum_T_time += T_time;
    		sum_QT_time += QT_time;
    		int pre = pronum;
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pronum++;
    			}
    		}
    		sortWithPriority(pro,pre,pronum);//将到达的进程按照服务时间排序
    		for(int i=pre;i<pronum;i++){    //将进程链入队列 
    			EnterQueue(queue,&pro[i]);
    		}
    		pre = pronum;
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time
    			,T_time,QT_time);
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	} 
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    }
    

    (4)时间片轮转(RR)
    算法思想:
    ①首先也是按进程的到达时间进行排序。让最先到达的进程入队。
    ②当队列不空时,从队头取出一个进程来执行。此时分两种情况
    2.1、如果当前进程的剩余服务时间不大于时间片大小,说明此次将会将这个进程执 行完毕,在此进程执行过程中到达的进程需要添加到进程就绪队列中,这时就可以输出 此进程执行完毕。
    2.2、如果当前进程的剩余服务时间大于时间片大小,还需将此进程执行过程中到达 的进程需要添加到进程就绪队列中,然后此进程的剩余服务时间减少时间片大小,此进 程重新进入进程就绪队列。
    ③此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    void RR(program pro[],int num){
    	printf("请输入时间片大小"); 
    	int timeslice;scanf("%d",&timeslice);
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	pro[0].start_time = pro[0].enter_time;
    	EnterQueue(queue,&pro[0]);
    	int time = 0;
    	int pronum = 1;
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);    // 从队列中取出头节点 
    		if(time<curpro->enter_time)
    			time = curpro->enter_time;
    		if(timeslice >= curpro->running_time){   // 如果剩余时间小于时间片  则此任务完成
    			for(int tt = time;tt<=time+curpro->running_time&&pronum<num;tt++){    // 模拟进程的执行过程 
    				if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    					pro[pronum].start_time = tt;
    					EnterQueue(queue,&pro[pronum]);
    					pronum++;
    				}
    			}
    			time += curpro->running_time;
    			curpro->running_time = 0;
    			curpro->done_time = time;
    			int T_time = curpro->done_time-curpro->start_time;
    			float QT_time = T_time / (curpro->copyRunning_time+0.0);
    			sum_T_time += T_time;
    			sum_QT_time += QT_time;
    			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n",curpro->name,curpro->enter_time,curpro->copyRunning_time,
    				curpro->start_time,curpro->done_time,T_time,QT_time);
    			if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    				pro[pronum].start_time = pro[pronum].enter_time;
    				EnterQueue(queue,&pro[pronum]);
    				pronum++; 
    			}
    			continue; 
    		}
    		for(int tt = time;tt<=time+timeslice&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pro[pronum].start_time = tt;
    				EnterQueue(queue,&pro[pronum]);
    				pronum++;
    			}
    		}
    		time += timeslice;
    		curpro->running_time -= timeslice; 
    		EnterQueue(queue,curpro);    //当前程序未完成  继续添加到队列中 
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			pro[pronum].start_time = pro[pronum].enter_time;
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    } 
    

    完整c语言代码

    #include<stdio.h>
    #include<malloc.h>
    #include<string.h> 
    #include<stdlib.h>
    typedef struct program{
    	char name[20];
    	int running_time;
    	int enter_time;
    	int priority;
    	int done_time;    //用于时间片轮转
    	int copyRunning_time;  //用于时间片轮转
    	int start_time; 
    	program* next;
    } Program;
    typedef struct programQueue{
    	program* firstProg;
    	program* LastProg;
    	int size;
    } programQueue;
    void Queueinit(programQueue* queue){
    	if(queue==NULL){
    		return ;
    	}
    	queue->size = 0;
    	queue->LastProg = (program*)malloc(sizeof(program));
    	queue->firstProg = queue->LastProg;
    }
    void print(program pro[],int num){
    	for(int i=0;i<num;i++){
    		printf("%d ",pro[i].enter_time);
    	}
    }
    void printQueue(programQueue* queue){
    	program* p=queue->firstProg->next;
    	while(p!=NULL){
    		printf("%s ",p->name);
    		p=p->next;
    	}
    	printf("\n");
    } 
    void EnterQueue(programQueue* queue,program* pro){   //加入进程队列 
    	queue->LastProg->next = (program*)malloc(sizeof(program));
    	queue->LastProg = queue->LastProg->next; 
    	queue->LastProg->enter_time = pro->enter_time;
    	memcpy(queue->LastProg->name,pro->name,sizeof(pro->name));   
    	queue->LastProg->priority = pro->priority;
    	queue->LastProg->running_time = pro->running_time;
    	queue->LastProg->copyRunning_time = pro->copyRunning_time;
    	queue->LastProg->start_time = pro->start_time;
    	queue->size++;
    }
    program* poll(programQueue* queue){
    	program* temp = queue->firstProg->next;
    	if(temp == queue->LastProg){
    		queue->LastProg=queue->firstProg;
    		queue->size--;
    		return temp;
    	}
    	queue->firstProg->next = queue->firstProg->next->next;
    	queue->size--;
    	return temp;
    }
    void inputProgram(program pro[],int num){
    	for(int i=0;i<num;i++){
    		program prog ;
    		printf("请输入第%d个进程的名字,到达时间,服务时间,优先级\n",i+1);
    		scanf("%s",prog.name);
    		scanf("%d",&prog.enter_time) ;
    		scanf("%d",&prog.running_time);
    		prog.copyRunning_time = prog.running_time; 
    		scanf("%d",&prog.priority);
    		pro[i]=prog;
    	}
    }
    void sortWithEnterTime(program pro[],int num){
    	for(int i=1;i<num;i++){
    		for(int j= 0;j<num-i;j++){
    			if(pro[j].enter_time>pro[j+1].enter_time){
    				program temp = pro[j];
    				pro[j] = pro[j+1];
    				pro[j+1] = temp;
    			}
    		}
    	}
    }
    
    void FCFS(program pro[],int num){
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);    //按照进入顺序排序 
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    	Queueinit(queue);
    	EnterQueue(queue,&pro[0]);
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前的进程 
    	float sum_T_time = 0,sum_QT_time = 0 ; 
    	while(queue->size>0){
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		sum_T_time += T_time;
    		float QT_time = T_time / (curpro->running_time+0.0) ;
    		sum_QT_time += QT_time;
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    		
    			if(tt>=pro[pronum].enter_time){
    				EnterQueue(queue,&pro[pronum]);
    				pronum++;
    			}
    		}
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time
    			,T_time,QT_time);
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    }
    void sortWithLongth(program pro[],int start,int end){
    	int len = end - start;
    	if(len == 1) return ;
    	for(int i=1;i<len;i++){
    		for(int j= start;j<end-i;j++){
    			if(pro[j].running_time>pro[j+1].running_time){
    				program temp = pro[j];
    				pro[j] = pro[j+1];
    				pro[j+1] = temp;
    			} 
    		}
    	}
    }
    void SJF(program pro[],int num) {
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	EnterQueue(queue,&pro[0]);
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前的进程 
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		float QT_time = T_time / (curpro->running_time+0.0) ;
    		sum_T_time += T_time;
    		sum_QT_time += QT_time;
    		int pre = pronum;
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pronum++;
    			}
    		}
    		sortWithLongth(pro,pre,pronum);//将到达的进程按照服务时间排序
    		for(int i=pre;i<pronum;i++){    //将进程链入队列 
    			EnterQueue(queue,&pro[i]);
    		}
    		pre = pronum;
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time
    			,T_time,QT_time);
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/num);
    }
    void sortWithPriority(program pro[],int start,int end){
    	int len = end - start;
    	if(len == 1) return ;
    	for(int i=1;i<len;i++){
    		for(int j= start;j<end-i;j++){
    			if(pro[j].priority>pro[j+1].priority){
    				program temp = pro[j];
    				pro[j] = pro[j+1];
    				pro[j+1] = temp;
    			} 
    		}
    	}
    }
    void HPF(program pro[],int num){
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	EnterQueue(queue,&pro[0]);
    	int time = pro[0].enter_time;
    	int pronum=1;    //记录当前的进程 
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if(time<curpro->enter_time)
    			time =  curpro->enter_time;
    		int done_time = time+curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		float QT_time = T_time / (curpro->running_time+0.0) ;
    		sum_T_time += T_time;
    		sum_QT_time += QT_time;
    		int pre = pronum;
    		for(int tt = time;tt<=done_time&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pronum++;
    			}
    		}
    		sortWithPriority(pro,pre,pronum);//将到达的进程按照服务时间排序
    		for(int i=pre;i<pronum;i++){    //将进程链入队列 
    			EnterQueue(queue,&pro[i]);
    		}
    		pre = pronum;
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n",curpro->name,curpro->enter_time,curpro->running_time,time,done_time
    			,T_time,QT_time);
    		time +=  curpro->running_time;
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	} 
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    }
    void RR(program pro[],int num){
    	printf("请输入时间片大小"); 
    	int timeslice;scanf("%d",&timeslice);
    	printf("进程 到达时间  服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro,num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));;
    	Queueinit(queue);
    	pro[0].start_time = pro[0].enter_time;
    	EnterQueue(queue,&pro[0]);
    	int time = 0;
    	int pronum = 1;
    	float sum_T_time = 0,sum_QT_time = 0;
    	while(queue->size>0){
    		program* curpro = poll(queue);    // 从队列中取出头节点 
    		if(time<curpro->enter_time)
    			time = curpro->enter_time;
    		if(timeslice >= curpro->running_time){   // 如果剩余时间小于时间片  则此任务完成
    			for(int tt = time;tt<=time+curpro->running_time&&pronum<num;tt++){    // 模拟进程的执行过程 
    				if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    					pro[pronum].start_time = tt;
    					EnterQueue(queue,&pro[pronum]);
    					pronum++;
    				}
    			}
    			time += curpro->running_time;
    			curpro->running_time = 0;
    			curpro->done_time = time;
    			int T_time = curpro->done_time-curpro->start_time;
    			float QT_time = T_time / (curpro->copyRunning_time+0.0);
    			sum_T_time += T_time;
    			sum_QT_time += QT_time;
    			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n",curpro->name,curpro->enter_time,curpro->copyRunning_time,
    				curpro->start_time,curpro->done_time,T_time,QT_time);
    			if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    				pro[pronum].start_time = pro[pronum].enter_time;
    				EnterQueue(queue,&pro[pronum]);
    				pronum++; 
    			}
    			continue; 
    		}
    		for(int tt = time;tt<=time+timeslice&&pronum<num;tt++){    //模拟进程的执行过程 
    			if(tt>=pro[pronum].enter_time){ // 统计从此任务开始到结束之间有几个进程到达 
    				pro[pronum].start_time = tt;
    				EnterQueue(queue,&pro[pronum]);
    				pronum++;
    			}
    		}
    		time += timeslice;
    		curpro->running_time -= timeslice; 
    		EnterQueue(queue,curpro);    //当前程序未完成  继续添加到队列中 
    		if(queue->size==0&&pronum<num){   //防止出现前一个进程执行完到下一个进程到达之间无进程进入 
    			pro[pronum].start_time = pro[pronum].enter_time;
    			EnterQueue(queue,&pro[pronum]);
    			pronum++; 
    		}
    	}
    	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n",sum_T_time/(num+0.0),sum_QT_time/(num+0.0));
    } 
    void choiceMenu(){
    	printf("请选择进程调度算法:\n\n");
    	printf("1.先来先服务算法\n2.短进程优先算法\n3.高优先级优先\n4.时间片轮转算法\n\n"); 
    }
    void menu(){
    	int proNum;
    	printf("请输入进程的个数:");
    	scanf("%d",&proNum);
    	program pro[proNum];
    	inputProgram(pro,proNum);
    	choiceMenu();
    	int choice;
    	while(1){
    		scanf("%d",&choice);
    		switch(choice){
    			case 1:system("cls");FCFS(pro,proNum);choiceMenu();break; 
    			case 2:system("cls");SJF(pro,proNum);choiceMenu();break; 
    			case 3:system("cls");HPF(pro,proNum);choiceMenu();break;
    			case 4:system("cls");RR(pro,proNum);choiceMenu();break;
    			case 5:return;
    		}
    	}
    	
    }
    int main(){
    	menu();
    	return 0;
    } 
    

    结果测试

    在这里插入图片描述

    结果按照完成时间输出

    先来先服务
    在这里插入图片描述
    短进程优先
    在这里插入图片描述
    高优先级优先
    在这里插入图片描述
    时间片轮转 时间片大小为10
    在这里插入图片描述

    展开全文
  • 操作系统进程调度算法 先来先服务 短作业优先 时间片轮转 优先级。有大量注释,帮助理解。目前没有错误
  • 大连理工大学软件学院数操作系统进程调度算法
  • 进程调度算法的设计 设计要求: ①设计进程控制块PCB表结构,分别适用于优先数调度算法和循环轮转调度算法。 ②建立进程就绪队列。对两种不同算法编制入链子程序。 ③编制两种进程调度算法:1)优先数调度;2)...
  • 进程调度算法模拟 专业 XXXXX 学号 XXXXX 姓名 XXX 实验日期 20XX 年 XX 月 XX 日 一实验目的 通过对进程调度算法的模拟加深对进程概念和进程调度算法的理解 二实验要求 编写程序实现对 5 个进程的调度模拟 要求至少...
  • 操作系统进程调度算法课程设计报告(包含报告,程序源代码,截图等)
  • 进程调度算法模拟。通过对进程调度算法的模拟,进一步理解进程的基本概念,加深对进程运行状态和进程调度过程、调度算法的理解。 (1) 用C、C++、Java语言编程实现对5个进程采用动态优先权调度算法进行调度的过程。...
  • 进程调度算法:根据系统的资源分配策略所规定的资源分配...硬件与软件有很多相通的数据处理方式,如何在空间和时间做取舍是共同的话题,总结学习操作系统中几种进程调度算法,抛砖引玉,期待能从中发散思维,收获满满。


    进程调度算法:根据系统的资源分配策略所规定的资源分配算法。硬件与软件有很多相通的数据处理方式,如何在空间和时间做取舍是共同的话题,总结学习操作系统中几种进程调度算法,抛砖引玉,期待能从中发散思维,收获满满。

    进程调度采用什么办法是与系统的设计目标相一致的,在批处理系统中,系统的设计目标是增加系统吞吐量和提高系统资源的利用率,而分时系统保证分时用户能容忍的响应时间。

    1.1 先来先去服务算法(FCFS)

    该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。和硬件的FIFO一个道理,不多余赘述。

    1.2 短作业(进程)优先调度算法

    短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。

    1.3 优先权调度算法

    照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。

    1.3.1 非剥夺式优先权算法

    系统把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机重新分配给另一优先权最高的进程。这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。

    1.3.2 剥夺式优先权调度算法

    在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。

    FIFO和SJF都是非剥夺式的调度算法,而最短完成时间优先算法(STCF)是剥夺式的调度算法。时间间隔是系统设计过程中进程之间的相互调度,时间周期是一开始单个进程所定义。

    上面几种方法性能非最优,但在设计复杂度上较低。

    1.4 高响应比优先调度算法

    wKioL1dWglWCMjz3AAAkh_DtQUc206.png

    为每个作业引入动态优先权,并使作业的优先级随着等待时间的增加而以速率a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为上图。

    1. 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。
    2. 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。
    3. 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高,从而也可获得处理机。简言之,该算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期得不到服务。因此,该算法实现了一种较好的折衷。当然在利用该算法时,每要进行调度之前,都须先做响应比的计算,这会增加系统开销

    1.5 Round-Robin调度算法

    响应时间还能更优化,只需在最短完成时间有限的调度算法上添加一个功能:指定每个进程最多只运行一段固定的时间,调度时轮询每一个进程。也就是轮询(Round-Robin,RR)调度算法。硬件上更好实现的是间隔固定的时间周期,但硬件的“进程”无法很好划分。时间片越短,RR在响应时间上表现越好,但是时间片太短也是有问题的,因为上下文切换频繁意味着它的代价越高。时间片也不能太长,时间片越长,RR在响应时间上表现越差,交互性越差。所以需要权衡时间片的长短在允许的条件下让时间片足够长。

    1.6 多级反馈队列调度算法

    如果未指明进程的时间周期,此种方法较为适用。优化未知问题的场景有时候非常关键,例如CPU的分支预测、缓存算法以及进程调度等等。解决这类问题的思路就是观察历史,从历史数据中推测未来。既然是预测,自然会有预测失败的时候,而预测失败的代价可能会比正常情况下更大,所以需要不断优化预测问题的方式,并提供预测失败时的挽救手段,尽量减小代价。

    (1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。

    (2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。

    (3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。

    • 如果优先级A大于B,则调度A

    • 如果优先级A等于B,则RR调度A和B

    • 进程刚启动时,放入最高优先级队列

    • 进程耗尽时间片后,降低该进程的优先级(移入下一级队列)

    • 如果在时间片内进行IO而主动放弃CPU,则保持其优先级不变

      总结汇总如摘抄图下👇👇👇👇

      img

      FCFS:先来先服务算法 SPN/SRT:短作业优先算法 HRRN:高响应比优先算法 RR:时间片轮转算法

      Priority:优先级调度算法 MFQ:多级反馈队列算法

    概念补充

    CPU繁忙:是指的这项作业的CPU计算部分的时间需要占用大量的时间,很少请求I/O。对应于I/O繁忙,作业很是频繁的请求I/O,真正用于计算的时间却不多,因此可以认为CPU繁忙的作业更接近于长作业的工作方式,因为它长时间占用了CPU,I/O繁忙更接近于短作业的工作方式。

    剥夺方式: 当一个进程正在处理器上执行时,系统可以根据规定的原则剥夺分配给它的处理器,而把处理器分配给其他进程使用。有两种常见的剥夺原则:高优先级剥夺原则时间片剥夺原则,前者高优先级进程或线程可以剥夺低优先级进程或线程运行,后者当运行进程时间用完后被剥夺处理器。非剥夺方式: 一旦某个进程或线程开始执行后便不再出让处理器,除非该进程或线程运行结束或发生了某个事件不能继续执行。

    响应时间:进程未运行到下次被选中运行的时间间隔。例如进程刚被创建到第一次调度到它的时间间隔,再例如从该进程切换走后到下次调度到该进程的时间间隔。响应时间体现了交互性,响应时间越短,交互性越好。例如从键盘敲下一个字符,如果需要等待几秒钟才出现到屏幕,这个交互性是非常差的。周转时间:进程从启动开始到执行完成所花费的时间。周转时间体现的性能,周转时间越短,说明进程从开始到完成等待的时间越短。

    参考文档

    【1】操作系统修炼秘籍(26):进程调度算法图解说明 -->推荐

    【2】常见的几种操作系统进程调度算法

    【3】五种进程调度算法的总结;

    【4】挑战408——操作系统(8)——典型的调度算法

    【5】操作系统调度算法简介

    【6】列出目前 OS 涉及到的几种进程调度算法,并简述对他们的理解

    【7】操作系统中常用的进程调度算法

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 109,551
精华内容 43,820
关键字:

操作系统进程调度算法