线程上下文切换和CPU模式切换点的核心执行流程

Core execution flow in the point of thread context switch and CPU mode switch

如果

我想知道在线程上下文切换和每个时间片 CPU 模式切换方面的简化核心执行流程。

我的理解如下。如有错误请指正

如果线程是内核管理的用户模式线程,不涉及中断,或任何需要内核模式的线程,

  1. 发生线程上下文切换。
  2. 核心执行线程切换到内核模式,因为根据, here and here上下文切换只能发生在内核模式,除非线程是用户管理的线程。
  3. 核心执行线程切换到用户态
  4. 内核执行位于用户 space 中的指令序列。
  5. 时间片到期。
  6. 重复 1。

我能找到的最接近的相关图表如下。

即使是一点线索也将不胜感激。

你自己说的:

context switch can only occur in kernel mode

所以 CPU 必须进入内核模式 可以进行上下文切换之前。在大多数操作系统中,这可能以两种方式之一发生:

  1. user-mode代码进行系统调用,或者
  2. 发生中断。

如果线程通过进行系统调用进入内核模式,那么如果系统调用导致线程不再 运行nable(例如,sleep() 调用,则可能会进行上下文切换),或者如果系统调用导致某些 higher-priority 线程变为 运行 可用,则可能存在上下文切换。 (例如,系统调用释放更高优先级线程正在等待的互斥量。)

如果线程因为中断进入内核模式,那么可能会有上下文切换,因为中断处理程序使一些 higher-priority 线程 运行nable(例如,如果另一个线程正在等待来自磁盘的数据),或者可能是上下文切换,因为它是一个定时器中断,并且当前线程的时间片已经过期。


上下文切换的机制在不同的硬件平台上可能会有所不同。这是如何发生在某些假设的CPU:

  1. 当前线程 (threadA) 进入 sheduler 代码,该代码选择一些其他线程 (threadB) 作为当前 CPU 上 运行 的下一个。
  2. 它调用了一些 switchContext(threadB) 函数。
  3. switchContext 函数将值从堆栈指针寄存器和其他活动寄存器复制到当前线程 (threadA) 的已保存上下文区域。*
  4. 然后将“当前线程”指针设置为指向线程 B 的已保存上下文区域,并通过反向复制所有相同的内容来恢复线程 B 的上下文。**
  5. 最后,switchContext 函数 returns... IN threadB,... 在 threadB 最后一次调用它的地方。

最终,threadB returns 从中断或系统调用到应用程序代码 运行ning 在 user-mode.


* switchContext 的作者可能不得不小心,可能不得不做一些棘手的事情,以保存整个上下文而不破坏它。例如,最好不要 使用 任何需要保存的寄存器,然后才将其实际保存在某处。

** 最棘手的部分是恢复堆栈指针寄存器时。一旦发生这种情况,“the”堆栈突然是线程 B 的堆栈而不是线程 A 的堆栈。