CPU调度决策可能发生在以下四种情况下。

  1. 当进程从运行(running)状态切换到等待(waiting)状态时(例如,由于I/O请求或调用wait()等待某个子进程终止)
  2. 当进程从运行(running)状态切换到就绪(ready)状态时(例如,当出现中断时)
  3. 当进程从等待(waiting)状态切换到就绪(ready)状态时(例如,I/O完成时)
  4. 当一个进程终止时

对于第1和第4种情况,没有其他选择只能调度。一个新的进程(如果存在于就绪队列中)必须被选择用于执行。然而,在情况2和3,可以进行选择。

当调度只能发生在第1和第4种情况下,那么成这样的调度方案是非抢占式的或者协作的;否则,称调度方法是抢占式的。采用非抢占式调度,一旦CPU分给一个进程,那么该进程会一直使用CPU直到进程终止或者切换到等待状态。Windows3.x使用的就是这种调度方法,Window95引入了抢占调度,所以之后的所有Windows系统都是抢占式。协作调度/非抢占式调度在有的硬件平台上是唯一的选择,因为它不要求具有强占式调度所需要的特定的硬件(比如定时器)的支持。

不幸的是,当数据在多个进程之间共享时,抢占式调度可能导致竞态条件。考虑共享数据的两个进程的情况。当一个进程更新数据时,它被抢占,以便第二个进程可以运行。然后,第二个进程尝试读取数据,这些数据处于不一致的状态。这个问题在第五章中有详细的探讨。

强占调度对于操作系统的内核的设计也有影响。在处理系统调用时,内核可能忙于进程活动,这些活动可能涉及到要改变重要内核数据(如I/O队列)。如果一个进程在进行这些修改的时候被强占,内核(或者设备驱动)需要读取或者修改这个相同的结构,那么会产生什么后果呢??肯定会导致混乱。有的操作系统,包括绝大多数的Unix系统,通过在上下文切换之前等待系统调用完成或者等待发生I/O阻塞来处理这一问题。不幸的是,这种内核执行模型对于支持实时计算来说是很糟糕的,因为任务必须在给定的时间框架内完成执行。在第6.6节中,我们探讨了实时系统的调度需求。

因为根据定义,中断可以随时发生,而且因为它们不能总是被内核所忽略,所以受中断影响的代码段必须加以保护以避免同时使用。操作系统几乎在任何时候都能接受中断。否则,输入可能会丢失或输出也会被改写。因此,这些代码段不能同时被多个进程访问,它们在进入时禁用中断,而在退出时,重新启用中断。需要注意的是,禁用中断的代码段并不经常发生,而且通常只包含很少的指令。

results matching ""

    No results matching ""