短期调度程序是否需要上下文切换到 运行?
Is a context switch needed for the the short-term scheduler to run?
我的理解是短期调度程序是内核中的一个模块(我猜它本身就是一个进程?)。这经常被 运行 检查并决定它是否应该抢占 运行ning 进程(可能是因为 SJF 和到达的更短的工作)。
如果这是正确的,我的直觉表明,对于 运行 的短期调度程序,必须进行上下文切换:
- 保存 运行ning 进程的状态
- 加载新进程(短期调度程序)
- 让它决定哪个进程运行(比方说next_process)
- next_process 被分配到 CPU,因此其 PCB 被加载。
但是从我老师教给我们的情况来看,我认为这是不正确的。
- 我怎么错了,为什么错了?
- 短期调度程序如何在不发生上下文切换的情况下处理 运行?
让我们首先假设任务具有以下状态之一:
“目前 运行宁”。如果有 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?
调度器只是内核中的一组函数(而不是进程)。
我的理解是短期调度程序是内核中的一个模块(我猜它本身就是一个进程?)。这经常被 运行 检查并决定它是否应该抢占 运行ning 进程(可能是因为 SJF 和到达的更短的工作)。
如果这是正确的,我的直觉表明,对于 运行 的短期调度程序,必须进行上下文切换:
- 保存 运行ning 进程的状态
- 加载新进程(短期调度程序)
- 让它决定哪个进程运行(比方说next_process)
- next_process 被分配到 CPU,因此其 PCB 被加载。
但是从我老师教给我们的情况来看,我认为这是不正确的。
- 我怎么错了,为什么错了?
- 短期调度程序如何在不发生上下文切换的情况下处理 运行?
让我们首先假设任务具有以下状态之一:
“目前 运行宁”。如果有 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”(无论下一个任务之前的状态如何)。
从某处加载下一个任务的“CPU状态”(注册内容等)。
如果之前有一个 运行ning 任务,将之前 运行ning 任务的“CPU 状态”(注册内容等)保存在某处(例如在某种结构)。
How can the short-term scheduler process run without a context switch to happen for it?
调度器只是内核中的一组函数(而不是进程)。