上下文切换指的是内核(操作系统的核心)在CPU上对进程或者线程进行切换。上下文切换过程中的信息被保存在进程控制块(PCB-Process Control Block)中。PCB又被称作切换桢(SwitchFrame)。上下文切换的信息会一直被保存在CPU的内存中,直到被再次使用。1
概述上下文切换 (context switch) , 其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运行另外的任务时, 它保存正在运行任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中, 入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器, 并开始下一个任务的运行, 这一过程就是context switch。2
每个任务都是整个应用的一部分, 都被赋予一定的优先级, 有自己的一套CPU寄存器和栈空间, 如图所示。2
基本原理上下文切换的基本原理就是当发生任务切换时, 保存当前任务的寄存器到内存中, 将下一个即将要切换过来的任务的寄存器状态恢复到当前CPU寄存器中, 使其继续执行, 同一时刻只允许一个任务独享寄存器。在任务切换的过程中是涉及任务上下文的保存和恢复操作, 而任务上下文切换操作的性能是衡量操作系统性能的一个重要指标。任务上下文切换指标可以反映出操作系统在多任务环境下的处理能力。3
流程上下文的切换流程如下1
(1)挂起一个进程,将这个进程在CPU中的状态(上下文信息)存储于内存的PCB中。1
(2)在PCB中检索下一个进程的上下文并将其在CPU的寄存器中恢复。1
(3)跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行)并恢复该进程。1
时间片轮转方式使多个任务在同一CPU上的执行有了可能,具体过程如图所示。1
引起线程上下文切换的原因引起线程上下文切换的原因如下1
(1)当前正在执行的任务完成,系统的CPU正常调度下一个任务。
(2)当前正在执行的任务遇到I/O等阻塞操作,调度器挂起此任务,继续调度下一个任务。
(3)多个任务并发抢占锁资源,当前任务没有抢到锁资源,被调度器挂起,继续调度下一个任务。
(4)用户的代码挂起当前任务,比如线程执行sleep方法,让出CPU。
(5)硬件中断。1
上下文切换开销上下文切换是操作系统内核优化的一个关键参数指标。在任务间发生切换需要花费大量的时间用于处理诸如:保存和恢复寄存器和内存页表、更新内核相关数据结构等操作。上下文切换通常是计算密集型的。也就是说, 它需要相当可观的处理器时间, 在每秒几十上百次的切换中, 每次切换都需要纳秒量级的时间。所以, 上下文切换对系统来说意味着消耗大量的CPU时间。4
从Linux内核内部实现来看, 如图所示, 上下文切换所花费的延迟时间是从调度器选好要调度的任务 (任务1) 后到把任务上下文切换到另一个任务 (任务2) 所花费的时间。即context_switch () 函数的开销。4
性能影响上下文切换会对性能造成负面影响。一些上下文切换相对其他切换而言更加昂贵;其中一个更昂贵的上下文切换是跨核上下文切换(Cross-Core Context Switch)。一个线程可以运行在一个专用处理器上,也可以跨处理器。由单个处理器服务的线程都有处理器关联(Processor Affinity),这样会更加有效。在另一个处理器内核抢占和调度线程会引起缓存丢失,作为缓存丢失和过度上下文切换的结果要访问本地内存。总之,这称为“跨核上下文切换”。5
本词条内容贡献者为:
肖志勇 - 副教授 - 江南大学