在多道程序设计设计之前,没有CPU调度的概念。因为单道程序不需要调度CPU。
问:为什么需要调度?
答:使计算机更加高效。(例如,不能因为等待IO操作,而让CPU闲着)
每当CPU空闲时,操作系统就应从就绪队列中选择一个进程来执行。
注意:就绪队列不必是先进先出(FIFO)的,可以是先进先出(FIFO)队列、优先队列、树、或简单的无序链表等。
就绪队列内的内容为进程控制块(PCB)。
4 种情况时需要进行进程调度:
调度程序的功能包括:
为了比较各种CPU调度算法的优劣,要有一些调度准则。包括:
完美的操作系统应该是:最大化的CPU使用率、吞吐量和最小化周转时间、等待时间、响应时间。
本节只讨论常见的6个调度算法。
先到先服务(First-Come,First-Serverd, FCFS)。
就绪队列可以使用FIFO队列实现。
非抢占式的。
缺点:平均等待时间往往很长。会有护航效果(其他进程都在等待一个进程释放CPU),对于分时系统来说非常麻烦。
最短作业优先调度(Shortest-Job-First, SJF).
更为准确的叫法是:下次最短CPU执行。选择下次最短的进程来执行。
抢占和非抢占。
优点:平均等待时间、平均周转时间最少。
难点:如何知道下次CPU执行的长度?因此就有了一些算法来预测下一次的执行长度。
缺点:容易出现饥饿或无穷阻塞(对长作业长期不被调度)。
优先级调度(priority-scheduling)。
每一个进程都有一个优先级与其关联。
抢占和非抢占。
优先级分为内部和外部:内部的如(时限、内存要求、打开文件数量、IO时间等)。
外部的(进程重要性、赞助部门、费用【充钱了网速当然快啊】等……)
缺点:容易出现饥饿或无穷阻塞。
解决方法:老化逐渐增加系统中等待很长时间的进程的优先级。
轮转调度(Round-Robin, RR)。
轮转调度是专门为分时系统设计的,类似于FCFS基础上增加了抢占。
有时间片(time slice)通常为10ms~100ms。就绪队列为循环队列,CPU循环整个就绪队列,每个进程分配不超过一个时间片的CPU。
抢占式
难点:时间片大小的设置。
把进程分为不同的组,每一组有一类的调度算法。
多级队列调度算法讲就绪队列分为多个单独队列。根据进程的属性,永久性的分到一个队列里。
各单独队列按优先级来排序,只有高优先级里的队列为空,低优先级的队列里的进程才可以执行。
各个单独的队列里有自己的调度算法。
在多级队列调度算法中,进程进入系统时被永久的分配到某个队列中。
多级反馈队列调度允许进程在队列中迁移。
多级反馈队列调度程序有各种参数。
是更为通用的算法。也是最复杂的算法。
上一章讲了线程。包括用户级线程和内核级线程。
用户级线程和内核级线程之间的一个区别在如何调度
对于多对一模型和多对多模型。系统的线程库调度用户级线程。竞争范围是进程竞争范围。
而对于一对一模型,竞争范围是系统竞争范围。
对于多处理器,有两种调度方法:
1 非对称多处理:一个处理器用来调度、IO处理等,其他处理器用来执行用户代码。
2 对称多处理(SMP):每个处理器自我调度。(所有进程可能处于一个共同的就绪队列中)
多处理器调度要考虑的问题:
1)处理器亲和性
一个进程最好一直让一个处理器来执行,否则要各种清理缓存,重新充填缓存。
2)负载平衡
不能让有的处理器空闲,有的处理器处于高负载。
负载平衡会抵消亲和性。
多核多进程
现在都是多核系统,多个处理器在一个物理芯片上。
当一个处理器访问内存时,花费大量的时间来等待所需数据,这叫做内存停顿。
为解决这个问题,硬件上采用多线程的处理器核。
例如,双线程双核系统中,操作系统会有4个逻辑处理器。UltraSPARC T3 CPU有16个处理器核,每个核有8个硬件线程。操作系统的角度讲,有128个逻辑处理器。
对于多核多线程,有两个级别的调度:
1 操作系统选择哪个线程运行在哪个逻辑处理器(硬件线程)上。
2 每个核如何决定运行哪个硬件线程。
实时计算机系统要求在截止日期之前得到结果,在截止日期之后得到是无用的。
实时调度算法包括:
单调速率
最早截止优先调度
Linux中只有任务(task)调度这一说法。
完全公平调度算法(Completely Fair Scheduler , CFS)是默认的Linux调度算法。
Linux系统的调度基于调度类,每个类都有一个特定优先级,内核针对不同的调度类,采用不同的调度算法。
根据第2节的调度准则来评估调度算法。
评估方法有:
确定性模型(分析评估法)
排队模型
仿真
实现
本章讲了进程管理中的进程调度,包括概念和一些算法。还有一些实例。