CPU调度策略


前言

问题引入:
当线程1阻塞,线程2 3都处于就绪态,该执行哪个呢?需要有调度策略

在这里插入图片描述
CPU调度的直观想法:

1.FIFO:先进先出 (排队)
2.Priority:优先级高的先执行

面对复杂的场景,这两种几乎行不通的。

CPU调度:即按一定的调度算法从就绪队列中选择一个进程,把CPU的使用权交给被选中的进程,如果没有就绪进程,系统会安排一个系统空闲进程或idle进程

CPU调度时机:发生在内核对中断/异常/系统调用处理后返回到用户态时

进程正常终止 或 由于某种错误而终止;
新进程创建 或 一个等待进程变成就绪;
当一个进程从运行态进入阻塞态;
当一个进程从运行态变为就绪态。

CPU调度算法衡量指标:

吞吐量 (Throughput): 每单位时间完成的进程数目;

周转时间TT (Turnaround Time):每个进程从提出请求到运行完成的时间;

响应时间RT(Response Time):从提出请求到第一次回应的时间;

CPU利用率(CPU Utilization):CPU做有效工作的时间比例;

等待时间(Waiting time):每个进程在就绪队列(ready queue)中等待的时间;

……

提示:以下是本篇文章正文内容

一、调度算法

设计调度算法的目的:

1.面对用户,目的是让用户满意
2.面对进程:CPU调度的目标是进程满意

进程满意:
尽快结束任务:周转时间(从任务进入到任务结束)短
响应用户操作快:响应时间(从操作发生到响应)短
系统内耗时间少:吞吐量(完成的任务量)

总原则:系统专注于任务执行,又能合理调配任务

1.FCFS(First Come, First Served)

先来先服务算法(FCFS——First Come First Serve)

按照进程就绪的先后顺序使用CPU。
特点:非抢占,公平,实现简单,长进程后面的短进程需要等很长时间,不利于用户体验

三个进程的处理时间分别为12,3,3,分两种进程到达顺序讨论
在这里插入图片描述
优点:调度算法简单

缺点:
1.平均等待时间波动较大,短的进程可能排在长的进程后面得到执行

2.I/O资源和CPU资源利用率较低,CPU密集型进程会导致I/O设备闲置,I/O密集型进程会导致CPU闲置

2.SJF(Shortest Job First)

最短作业优先(SJF——Shortest Job First):
具有最短完成时间的进程优先执行,非抢占

在这里插入图片描述

如果调度结果是 P1,P2,…,Pn,则平均周转时间为:
P1 + P2 + P3 + … + Pn = ∑(n + 1 - i) * Pi
P1的周转时间是 P1
P2的周转时间是 P1 + P2
……
Pn的周转时间中含有 n*P1 + (n - 1) * P2 + …
P1 计算的次数最多,需要把最短的任务放在前边

所以,这种方式平均周转时间最小。

3.RR(Round Robin)

时间片轮转调度算法(Round Robin——RR)
每个进程被分配一个时间片,允许该进程在该时间段运行,如果在时间片结束时该进程还在运行,则剥夺CPU并分配给另一个进程,如果该进程在时间片结RR束前阻塞或结束,则CPU立即进行切换。

特点:公平;有利于交互式计算,响应时间快;由于进程切换,时间片轮转算法要花费较高的开销;对进程表中不同进程的大小差异较大的有利,而对进程都是相同大小的不利。

时间片设计需要避免的两点:

1.时间片太大,等待的时间过长,极限的情况下退化成为FCFS算法

2.时间片太小,反应过于迅速,产生大量的上下文切换,会影响到系统的吞吐量

4.折中方案

我们可以设置优先级,设置前台任务和后台任务,前台任务优先级高,后台任务优先级低,定义前台任务队列和后台任务队列,只有前台任务没有了才调度后台任务

但是,如果一直有前台任务,后台任务一直得不到执行(优先级低的任务一直得不到执行)

所以,任务的优先级要动态调整
一般后台任务 耗时比较长,一旦后台任务转到前台执行,可能耗时很长,一直不释放CPU,前台任务的响应时间又没法保证,前后台任务都要设置时间片,后台任务转到前台,执行一段,要释放CPU,让其他任务执行
在这里插入图片描述

折中方案:短任务优先(减少周转时间)、以 轮转调度为核心,要设置优先级

二、Schedule()

schedule() 的目的是找到下一个任务 next,切换到下一个任务

源码:

// 任务0是一个闲置(idle)任务,只有当其他任务没有运行时才调用它
// 它不能被杀死,也不能睡眠。任务0中的状态信息“state”是从来不用的

void schedule(void)
{
    
    
	int i,next,c;
	struct task_struct ** p; // 任务结构体的指针的指针

/* check alarm, wake up any interruptible tasks that have got a signal */
// 检查 alarm(进程的报警定时值),唤醒任何已得到信号的可中断任务

	把p初始化为指向最后一个进程的地址的指针,逆向扫描所有进程,并跳过空指针
	for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
		if (*p) {
    
     //*p 指向当前进程的指针
		//jiffies是系统从开机算起的滴答数(每10ms/滴答)
			//判断定时器是否到期,如果到期需要在信号位图中置SIGALARM位,并且将定时器清0
			if ((*p)->alarm && (*p)->alarm < jiffies) {
    
     
					(*p)->signal |= (1<<(SIGALRM-1));
					(*p)->alarm = 0;
				}
			//如果信号位图中表示有非阻塞信号被递送,该任务的状态是可中断的,那么将该任务状态置为就绪
			if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
			(*p)->state==TASK_INTERRUPTIBLE)
				(*p)->state=TASK_RUNNING;   // 置为就绪可以执行状态
		}

/* this is the scheduler proper: */

// 进程的调度
	// 检查就绪的任务,判断下一个运行的任务。
	while (1) {
    
    
		c = -1;                 //从最后一个任务开始遍历任务数组
		next = 0;
		i = NR_TASKS;
		p = &task[NR_TASKS];

		//对就绪任务按照时间片进行排序 
		//比较每个就绪状态任务的counter值(任务运行时间的递减滴答计数)
		//哪一个值大,运行的时间还不长,next就指向哪一个任务号
		while (--i) {
    
    
			if (!*--p)
				continue;
			if ((*p)->state == TASK_RUNNING && (*p)->counter > c) //counter这里是时间片
			//判断是就绪态,并且 counter>-1,就给c和next赋值,遍历找到最大的counter
				c = (*p)->counter, next = i;
		}

		
		//如果比较得出有counter值不等于0的结果,或者系统中没有一个可运行的任务存在
		//则跳出循环,执行任务切换操作
		if (c) break;

		//如果所有任务的时间片都为0,那么重新计算各个任务的时间片,计算原则是根据优先级进行计算
      	//更新每个任务的counter值,然后再回到开始处比较
		//计算方法:counter = counter/2 + priority
		for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
			if (*p)
				(*p)->counter = ((*p)->counter >> 1) + //counter这里代表优先级
						(*p)->priority;
	}
	//把当前任务指针current指向任务号为next的任务,并切换到该任务中运行
	//若系统中没有其他可运行的任务,则next=0,所以调度去指向空闲任务
	switch_to(next);    // 任务切换,切换到任务号为next的任务,并允许
}

1.counter(时间片)

counter是典型的时间片, 所以是轮转调度, 保证了响应
do_timer 中 counter 减到0,就schedule
在这里插入图片描述

2.counter(优先级)

counter代表的优先级可以动态调整
阻塞的进程再就绪以后优先级高于非阻塞进程
在这里插入图片描述

总结

提示:这里对文章进行总结:

调度函数的核心处理部分:这是根据进程的时间片优先权调度机制,来选择随后要执行的任务。

它首先循环检查任务数组中的所有任务,根据每个就绪态任务剩余执行时间的值counter,选取该值最大的一个任务,并利用switch _(0)函数切换到该任务。

若所有就绪态任务的该值都等于零,表示此刻所有任务的时间片都已经运行完,于是就根据任务的优先权值pitority,重置每个任务的运行时间片值counter,再重新执行循环检查所有任务的执行时间片值。

猜你喜欢

转载自blog.csdn.net/qq_53144843/article/details/120477052