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

发布于 2025-01-16 00:19:40 字数 383 浏览 4 评论 0原文

我的理解是,短期调度程序是内核中的一个模块(我猜它本身就是一个进程?)。通常,运行此命令是为了检查并决定是否应该抢占正在运行的进程(可能是因为 SJF 和到达时作业较短)。

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

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

然而,从我的老师教给我们的内容来看,我认为这是不正确的。

  1. 我怎么以及为什么错了?
  2. 短期调度程序进程如何在没有上下文切换的情况下运行?

My understanding is that the short-term scheduler is a module in the kernel (a process in itself i guess?). Frequently this is being run to check and decide if it should preemptive the running process (may be because of SJF and a shorter job as arrived).

If that is correct, my intuition suggests that for the short-term scheduler to run a context switch has to happen:

  1. Save state of running process
  2. Load the new process (short-term scheduler)
  3. Let it decide which process to run (lets say next_process)
  4. next_process is being allocated the CPU and thus its PCB is loaded.

However I don't think this is correct, judging from what my teacher has taught us.

  1. How and why am I wrong?
  2. How can the short-term scheduler process run without a context switch to happen for it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼中杀气 2025-01-23 00:19:41

首先,我们假设任务的状态为以下之一:

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

  • “准备运行”。如果有 20 个任务和 8 个 CPU,那么可能有 12 个任务准备在一个 CPU 上运行。

  • “被阻止”。这是等待 IO(磁盘、网络、键盘...)、等待获取互斥锁、等待时间过去(例如 sleep())等。请注意,这包括以下内容:任务不知道(例如,从交换空间获取数据,因为任务试图访问实际上不在内存中的数据)。

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

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

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

其他可能导致任务切换的情况包括:

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

  • 已创建一个新任务。这与任务解锁基本相同(内核的其他部分通知调度程序,调度程序决定新任务是否会抢占当前正在运行的任务或导致 CPU 退出省电状态)。

  • 调度程序经常在两个或多个任务之间切换,以造成它们都在同时运行的错觉(时间复用)。在设计良好的现代系统中,只有当相同优先级的任务多于可用 CPU 且这些任务经常阻塞时,才会发生这种情况;这是极其罕见的。在某些情况下(例如实时系统中的“最早截止时间优先”调度算法)这可能是不可能的。

我的理解是,短期调度程序是内核中的一个模块(我猜它本身就是一个进程?)

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

  • 进行时间统计(计算出多少时间)距离上次已经过去了,并用它来更新统计信息,以便人们可以知道每个任务消耗了多少 CPU 时间,CPU 空闲了多少时间等。

  • 如果之前有一个正在运行的任务(如果 CPU 之前没有空闲过),则将之前正在运行的任务的状态从“当前正在运行”更改为其他状态(“准备运行”或“已阻止”)。

  • 如果有先前运行的任务,则将先前运行的任务的“CPU 状态”(寄存器内容等)保存在某处(例如某种结构中)。

  • 将下一个任务的状态更改为“当前正在运行”(无论下一个任务之前的状态是什么)。

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

短期调度程序进程如何在没有上下文切换的情况下运行?

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

Let's start by assuming a task has a state that is one of:

  • "currently running". If there are 8 CPUs then a maximum of 8 tasks can be currently running on a CPU at the same time.

  • "ready to run". If there are 20 tasks and 8 CPUs, then there may be 12 tasks that are ready to run on a CPU.

  • "blocked". This is waiting for IO (disk, network, keyboard, ...), waiting to acquire a mutex, waiting for time to pass (e.g. sleep()), etc. Note that this includes things the task isn't aware of (e.g. fetching data from swap space because the task tried to access data that isn't actually in memory).

Sometimes a task will do something (call a kernel function like read(), sleep(), pthread_mutex_lock(), etc; or access data that isn't in memory) that causes the task to switch from the "currently running" state to the "blocked" state. When this happens some other part of the kernel (e.g. the virtual file system layer, virtual memory management, ...) will tell the scheduler that the currently running task has blocked (and needs to be put into the "blocked" state); and the scheduler will have to find something else for the CPU to do, which will be either finding another task for the CPU to run (and switching the other task from "ready to run" to "currently running") or putting the CPU into a power saving state (because there's no tasks for the CPU to run).

Sometimes something that a task was waiting for occurs (e.g. the user presses a key, a mutex is released, data arrives from swap space, etc). When this happens some other part of the kernel (e.g. the virtual file system layer, virtual memory management, ...) will tell the scheduler that the task needs to leave the "blocked" state. When this happens the scheduler has to decide if the task will go from "blocked" to "ready to run" (and tasks that were using CPUs will continue using CPUs), or if the task will go from "blocked" to "currently running" (which will either cause a currently running task to be preempted and go from "currently running" to "ready to run", or will cause a previously idle CPU to be taken out of a power saving state). Note that in a well designed OS this decision will depend on things like task priorities (e.g. if a high priority tasks unblocks it preempt a low priority task, but if a low priority task unblocks then it doesn't preempt a high priority task).

On modern systems these 2 things (tasks entering and leaving the "blocked" state) are responsible for most task switches.

Other things that can cause task switches are:

  • a task terminates itself or crashes. This is mostly the same as a task blocking (some other part of the kernel informs the scheduler and the scheduler has to find something else for the CPU to do).

  • a new task is created. This is mostly the same as a task unblocking (some other part of the kernel informs the scheduler and the scheduler decides if the new task will preempt a currently running task or cause a CPU to be taken out of a power saving state).

  • the scheduler is frequently switching between 2 or more tasks to create the illusion that they're all running at the same time (time multiplexing). On a well designed modern system this only ever happens when there are more tasks at the same priority than there are available CPUs and those tasks block often enough; which is extremely rare. In some cases (e.g. "earliest deadline first" scheduling algorithm in a real-time system) this might be impossible.

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

The scheduler is typically implemented as set of functions that other parts of the kernel call - e.g. maybe a block_current_task(reason) function (where scheduler might have to decide which other task to switch to), and an unblock_task(taskID) function (where if the scheduler decides the unblocked task should preempt a currently running task it already knows which task it wants to switch to). These functions may call an even lower level function to do an actual context switch (e.g. a switch_to_task(taskID)), where that lower level function may:

  • do time accounting (work out how much time has passed since last time, and use that to update statistics so that people can know things like how much CPU time each task has consumed, how much time a CPU has been idle, etc).

  • if there was a previously running task (if the CPU wasn't previously idle), change the previously running task's state from "currently running" to something else ("ready to run" or "blocked").

  • if there was a previously running task, save the previously running task's "CPU state" (register contents, etc) somewhere (e.g. in a some kind of structure).

  • change the state of the next task to "currently running" (regardless of what the next task's state was previously).

  • load the next task's "CPU state" (register contents, etc) from somewhere.

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

The scheduler is just a group of functions in the kernel (and not a process).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文