短期调度程序是否需要上下文切换到 运行?

Is a context switch needed for the the short-term scheduler to run?

我的理解是短期调度程序是内核中的一个模块(我猜它本身就是一个进程?)。这经常被 运行 检查并决定它是否应该抢占 运行ning 进程(可能是因为 SJF 和到达的更短的工作)。

如果这是正确的,我的直觉表明,对于 运行 的短期调度程序,必须进行上下文切换:

  1. 保存 运行ning 进程的状态
  2. 加载新进程(短期调度程序)
  3. 让它决定哪个进程运行(比方说next_process)
  4. next_process 被分配到 CPU,因此其 PCB 被加载。

但是从我老师教给我们的情况来看,我认为这是不正确的。

  1. 我怎么错了,为什么错了?
  2. 短期调度程序如何在不发生上下文切换的情况下处理 运行?

让我们首先假设任务具有以下状态之一:

  • “目前 运行宁”。如果有 8 个 CPU,则当前最多可以 运行 在 CPU 上同时执行 8 个任务。

  • “准备 运行”。如果有 20 个任务和 8 个 CPU,那么在 CPU.

    上可能有 12 个任务准备 运行
  • “已阻止”。这是等待 IO(磁盘、网络、键盘...)、等待获取互斥锁、等待时间过去(例如 sleep())等。请注意,这包括任务不知道的事情的(例如,从交换 space 中获取数据,因为该任务试图访问实际上不在内存中的数据)。

有时任务会做一些事情(调用内核函数,如 read()sleep()pthread_mutex_lock() 等;或访问不在内存中的数据)导致从“当前 运行ning”状态切换到“阻塞”状态的任务。当这种情况发生时,内核的其他部分(例如虚拟文件系统层,虚拟内存管理,......)会告诉调度程序当前 运行ning 任务已经阻塞(并且需要放入“阻塞”状态);并且调度程序将不得不为 CPU 找到其他事情要做,这将是为 CPU 找到另一个任务到 运行 (并将另一个任务从“准备好”切换到 运行”到“当前 运行ning”)或将 CPU 置于省电状态(因为 CPU 到 运行 没有任务)。

有时会发生任务正在等待的事情(例如,用户按下一个键,释放互斥锁,数据从交换 space 到达,等等)。当这种情况发生时,内核的其他部分(例如虚拟文件系统层、虚拟内存管理等)将告诉调度程序任务需要离开“阻塞”状态。当这种情况发生时,调度程序必须决定任务是否将从“阻塞”变为“准备好 运行”(并且使用 CPUs 的任务将继续使用 CPUs),或者如果任务将从“阻塞”变为“当前 运行ning”(这将导致当前 运行ning 任务被抢占并从“当前 运行ning”变为“准备好 运行”,否则将导致之前空闲的 CPU 退出省电状态)。请注意,在设计良好的 OS 中,此决定将取决于诸如任务优先级之类的事情(例如,如果高优先级任务解除阻塞,它会抢占低优先级任务,但如果低优先级任务解除阻塞,则它不会抢占高优先级任务优先任务)。

在现代系统中,这两种情况(任务进入和离开“阻塞”状态)负责大多数任务切换。

其他可能导致任务切换的事情是:

  • 一个任务自行终止或崩溃。这与任务阻塞基本相同(内核的其他部分通知调度程序,调度程序必须为 CPU 找到其他事情)。

  • 创建了一个新任务。这在很大程度上与任务解锁相同(内核的其他部分通知调度程序,调度程序决定新任务是否抢占当前 运行ning 任务或导致 CPU 被取出省电状态)。

  • 调度程序经常在 2 个或更多任务之间切换,以创建它们都在同一时间 运行ning 的错觉(时间多路复用)。在设计良好的现代系统上,只有当具有相同优先级的任务多于可用 CPU 并且这些任务经常阻塞时,才会发生这种情况;这是非常罕见的。在某些情况下(例如 real-time 系统中的“最早截止日期优先”调度算法)这可能是不可能的。

My understanding is that the short-term scheduler is a module in the kernel (a process in itself i guess?)

调度程序通常实现为内核其他部分调用的一组函数 - 例如可能是一个 block_current_task(reason) 函数(调度程序可能必须决定切换到哪个其他任务)和一个 unblock_task(taskID) 函数(如果调度程序决定未阻塞的任务应该抢占当前 运行ning它已经知道要切换到哪个任务)。这些函数可能会调用更低级别的函数来执行实际的上下文切换(例如 switch_to_task(taskID)),其中该更低级别的函数可能:

  • 做时间核算(算出自上次以来已经过了多少时间,并用它来更新统计数据,以便人们可以知道每个任务消耗了多少 CPU 时间, CPU 闲置了多长时间等)。

  • 如果之前有一个 运行ning 任务(如果 CPU 之前没有空闲),将之前 运行ning 任务的状态从“目前 运行ning" 到别的地方("准备好 运行" 或 "已阻止")。

  • [=56=

    如果之前有一个 运行ning 任务,将之前 运行ning 任务的“CPU 状态”(注册内容等)保存在某处(例如在某种结构)。

  • 将下一个任务的状态更改为“当前 运行ning”(无论下一个任务之前的状态如何)。

  • 从某处加载下一个任务的“CPU状态”(注册内容等)。

How can the short-term scheduler process run without a context switch to happen for it?

调度器只是内核中的一组函数(而不是进程)。