CPU调度(CPU scheduling)
调度是什么?
在计算机中,调度
是分配完成一个工作
所需资源
的方法。工作
可指诸如线程threads
、进程processes
或者数据流data flows
这样的虚拟计算元素,这些虚拟计算元素将会被调度
按照一定顺序(in turn)分配到诸如处理器processors,又称CPU
、网络链路network links
或者扩展卡expansion cards
这样的硬件资源上。
调度器scheduler
就是执行调度工作的程序。调度器使得整个计算机系统的资源处于忙碌状态(又叫负载均衡load balancing),允许多用户有效地共享系统资源,或者达到指定的服务质量。调度器使得在单处理器(a single central processing unit,CPU)上通过多任务处理
,从而让其执行多个进程成为可能。
一个调度器根据目的不同而有多种不同的设计,如:吞吐量最大化、响应时间(response time)和等待时间(wait time)最小化、最低延迟等等。而实践中,这些目的往往是互相冲突的,因此调度器会曹勇一个权衡利弊的折中方案进行设计,其侧重点取决于用户需求。
操作系统中调度器的种类
调度器是操作系统的一个模块,能够选择将被CPU处理的下一个作业或者说下一个进程。操作系统提供三种调度器:长期调度器(long-term scheduler)、中期调度器(medium-term scheduler)、短期调度器(short-term scheduler),其名称中的“长、中、短”显示执行其功能的相对频率。
进程调度器 Process scheduler
是操作系统的一部分,决定了某个进程何时被CPU执行。通常它能暂停一个正在运行的进程,并将这个进程转到运行队列running queue
中,转而开始执行另一个进程,这样的调度器称为“抢占式调度器”,否则就是“协同调度器”。
-
长期调度器long-term scheduler:
又叫“准入调度器(admission schedular)”、“作业调度器”或者“高级调度器”,决定了任务或进程是否被允许载入就绪队列(ready queue)中(即主存内)。换句话说,这种调度将已进入系统并处于后背状态的作业按某种算法选择一个或一批,为其建立进程,并进入主机,当该作业执行完毕时,还负责回收系统资源【注:正在执行的程序即进程】。因此,这类调度器掌控着能在系统上运行的程序、决定并发的程度(是否要同时执行多个或少数进程,以及如何分配I/O密集型和CPU密集型进程)。
通常,大多数程序可以归为I/O密集型
和CPU密集型
。I/O密集型
程序将大多数时间花在了I/O操作而不是运算上,而CPU密集型
程序正好相反,它将大多数时间花在了运算上,而很少产生I/O操作。如何组合这两种类型的程序对于长期调度器来说非常重要:如果全是I/O密集型
程序,那么就绪队列几乎一直都是空的使得调度器无所事事;另一方面,若全是CPU密集型
程序,会导致I/O等待队列处于空队状态,使得一些设备没人用,这样一来系统资源分配就不均衡。 -
中期调度器Medium-term scheduler:
又称为“交换调度器”或者“中级调度器”,主要负责暂时将主存中的进程转移到二级存储设备(比如说硬盘),我们通常把这种行为称为“交换swapping”。
详细说,它将进程从主存或CPU竞争中移出来,从而降低多道程序设计的麻烦程度,这些被移出来的进程后面能被再次载入主存,并从中断的地方继续执行,看得出来,这样的操作可以随时调整进程在主存中的存在数量和时机。
从状态上说,中级调度就是按照给定的原则和策略,将处于外存交换区中就绪状态或等待状态的进程调入主存,或把处于主存就绪状态或主存等待状态的进程交换到外存交换区。
那究竟什么时候中期调度器工作呢?
比如主存中某个进程不咋活跃或者其优先级低(后面在二级存储设备中存在某个程序亟待运行),又或者是那些总是产生错误,发出Error的家伙,还或者是某个进程占用了大量的主存空间,这时中期调度器就会把他们放入交换区,以便腾出一些主存空间给其他需求更为迫切的进程使用。而当系统主存空间充足的时候,亦或者某个进程不在阻塞队列(即这个进程所需要的资源都已经准备好)中时,中期调度器又会将刚刚放入交换区中的进程重新载入主存(进入运行队列)中。
现在的许多系统支持将虚拟地址空间映射到二级存储设备中而不是交换区,中期调度器便可以通过将二进制文件视为“交换出去的进程swapped out processes”来扮演长期调度器的角色。这样,当需要二进制文件的一部分时,可以按需交换(又称“懒散加载lazy loaded”)。 -
短期调度器Short-term scheduler:
常常又被称为“CPU 调度器”、“进程调度器”、“微观调度器”或者“低级调度器”(我们通常说得调度就是指这个),决定了在一个时钟中断、I/O中断、系统调用其他种类信号之后,哪一个正处于就绪队列中且在主存中的进程能被CPU执行(将CPU控制权交给这个进程)。因此,短期调度器做出决定的频率比前两种调度器更加频繁——每隔一段非常短的时间片都得做出一次决定。这种调度器可以是抢占式的,即能够强行把一个正在CPU中执行的进程拽出(中断),然后把CPU分配给其他进程;也可以是非抢占式的。
抢占式调度器需要一个处于内核态kernel mode
、能被中断处理程序
捕获的可编程间隔定时器
才能实现。
-
分派程序Dispatcher:
与CPU调度功能相关的另一个部分是分派程序。分派程序是一个模块,用来把CPU的控制权交给由短期调度器选出来的进程。它通常具有下面的功能:
1)上下文切换context switches,当短期调度器选出一个新进程时,分派程序就立马保存现场(即当前正在被CPU执行的进程/线程的状态),接着马不停蹄地对被选中的新进程进行初始化或者加载这个新进程原先被保存的状态。
2)从内核模式切换到用户模式。
3)跳转到用户程序的合适位置,以便重新启动程序。
分派程序应该尽可能快,因为在每次进程切换时都会使用它。其实在进程切换期间,CPU实际上空闲了一段时间,为了提高CPU利用率,应该避免不必要的上下文切换。这段时间又被叫做“分派延迟dispatch latency”。