上下文切换保存了什么?

15

两个线程之间的上下文切换到底保存和恢复了哪些内容?

  • 在同一进程中
  • 在两个进程之间

TSS是什么?(虚拟内存描述符) - osgx
4个回答

11
这是一个相当复杂的问题,因为答案取决于许多因素:
1. 相关的 CPU
它甚至在同一系列中也会有很大的不同,例如为 SSE/MMX 操作添加的附加寄存器。
2. 操作系统,因为它控制着在上下文切换时触发的处理程序,并决定是否使用CPU的硬件(如果有)来协助上下文切换。
例如,Windows不使用英特尔硬件来做许多上下文切换存储,因为它不存储浮点寄存器。
3. 由程序启用的任何优化并能够通知操作系统其自身要求的模式
也许可以指示它不使用 FP 寄存器,所以不要理会它们;在具有可观察寄存器文件的体系结构(如大多数RISC设计)中,了解您只需要较小的子集即可获得相当大的好处。
总之,至少需要保存正在使用的通用寄存器和程序计数器寄存器(假设当前大多数 CISC/RISC 风格的通用 CPU 的普遍设计)。
请注意,仅尝试在上下文切换方面进行最少的工作是某些学术兴趣话题
Linux显然在公共领域中有更多相关信息,尽管我的参考资料可能有点过时。
有一个“task_struct”,其中包含大量与任务状态以及任务所属进程相关的字段。
其中之一是“thread_struct”。

/*此任务的特定于CPU的状态*/
- struct thread_struct thread;
包含有关缓存TLS描述符、调试寄存器、故障信息、浮点数、虚拟86模式或IO权限的信息。

每个架构都定义了自己的thread_struct,用于标识在切换时保存的寄存器和其他值。
这一问题的复杂性进一步增加了重命名寄存器的存在,这些寄存器允许多个指令同时执行(通过超标量或流水线相关的架构设计)。上下文切换的恢复阶段可能依赖于CPU流水线以最初为空状态被恢复,以使尚未在流水线中退役的指令无效,从而可以忽略它们。这使得CPU的设计变得更加困难。
进程和线程之间的区别在于,进程切换(在所有主流操作系统中始终意味着线程切换)需要更新内存翻译信息、与IO相关的信息和权限相关的结构。
这些将主要是对更丰富数据结构的指针,因此相对于线程上下文切换来说不会有很大的成本。

非常清晰的解释。不过我还想问一件事。在上下文切换发生后,我仍然无法弄清楚CPU中的PC寄存器如何在物理上更新? - stdout
“topic of some academic interest” 的链接目标已经失效了。那里曾经链接的文章名字是什么? - bshanks
回复:最小化上下文切换工作:例如,Linux过去在x86上执行“惰性”上下文切换,其中它保留FP / SIMD寄存器的状态不变,但设置了一个控制寄存器位,以使FP / SIMD指令发生错误。如果新进程确实运行了这样的指令,则会保存/恢复寄存器。但是与存储带宽相比,故障成本较高,现在每个进程都使用SIMD寄存器进行类似memcpy的操作,因此只支持“急切”的FPU / SIMD保存/恢复方法。不再需要跟踪哪个任务拥有FP寄存器状态。 - Peter Cordes

2

当上下文切换在同一进程的线程之间进行时,保存当前线程的所有非易失性通用寄存器,并恢复新线程的寄存器;如果当前线程执行被中断,则只需要保存易失性寄存器。线程使用的任何协处理器(例如浮点处理器)的寄存器也应该被保存和恢复。 如果切换在2个进程的线程之间进行,则除了正常上下文切换所需的内容外,还需要进行与内存和IO管理相关的更改;例如,进程所需的内存保护是通过页面表和页面目录表实现的,每个进程都有一个唯一的页面目录表地址,在进程更改时必须更改。


1
这取决于您使用的操作系统,但肯定需要保存所有寄存器(包括指令计数器)的内容,并加载您要切换到的线程的寄存器。
对于同一进程中两个线程之间的切换,我能想到的唯一区别是您不会丢失L1和MMU缓存的内容。

-3

我不确定,但如果我没记错的话,工作内存集也被切换了。


我不确定,但我认为这个答案并没有给人太多信心。需要更多细节吗? - jouell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接