目录

  1. 概述
  2. 上下文切换与模式切换
  3. 上下文的分类
  4. 上下文切换的花费
  5. 附录

本文翻译自Context Switch Definition,同时加入了部分我个人的理解,如果想要学习更加原始的知识请访问原网址进行学习😃

概述

上下文切换(有时也称为进程切换或任务切换)主要是将CPU 的使用权从一个进程/线程切换到另一个进程/线程

Context Switch

进程(有时也被称为任务)是正在执行的程序的一种抽象,在 Linux 系统中,线程是轻量级进程,它们可以相互之间并行运行,并且相互之间共享相同的地址空间以及共享它们父进程的一切资源(是由父进程创建的子线程)

❓什么是上下文?

  • 上下文就是在任意某一时刻,CPU寄存器以及程序计数器中保存的值

📖寄存器是 CPU 内部内存非常小但速度非常快(相比于在 CPU 外部作为主存的 RAM 而言)的一种设备,寄存器被用来去加速程序的执行速度,存储的通常是程序的中间结果变量

📖程序计数器是 CPU 内部一个特殊的寄存器,它指示 CPU 在其指令序列中的位置,并保存着正在执行的指令的地址或下一条要执行的指令的地址,这取决于具体系统的实现方式

✨上下文切换可以更详细地描述为内核(即操作系统的和核心)对 CPU 上的进程(包括线程)执行以下活动:

  1. 暂停一个正在某程序的进程,并将该进程的 CPU 状态(即上下文)存储在内存中的某个地方
  2. 从内存中获取下一个进程的上下文,并在 CPU 的寄存器中恢复它
  3. 返回程序计数器指示的位置(即返回进程被中断的代码行)以恢复进程

📓上下文切换某些时刻也被描述为:内核暂停在某个 CPU 上运行的进程并恢复先前被暂停的另一个进程

上下文切换与模式切换

🎶上下文切换仅发生在内核模式(内核模式是 CPU 的特权模式,其中只有内核运行,并提供对所有内存位置和所有其他系统资源的访问),其他的程序,例如应用程序,最初在用户模式运行,但是它们可以通过系统调用运行部分内核代码

📖系统调用是在类 unix 操作系统中,活动进程(即当前在 CPU 中运行的进程)对内核提供服务的一种请求,例如:I/O进程创建

类 unix 操作系统中存在这两种模式(用户模式、内核模式)意味着:通过系统调用将 CPU 切换到内核模式时,这种操作虽然简单但却是必须的,这被称为模式切换不是上下文切换,因为这并没有切换当前 CPU 上运行的进程

✨上下文切换与并发的关系

  • 上下文切换是多任务操作系统的一大重要特性,在多任务操作系统中,多个进程似乎同时在一个 CPU 上执行,彼此之间互不干扰
  • 这种并发错觉是通过快速连续发生的上下文切换(每秒十次或数百次)来实现的

❓什么原因会导致上下文切换?

  • 进程放弃它们在 CPU 中的执行时间
  • 调度器在进程耗尽其CPU 时间片时进行切换的结果
  • 硬件中断同样会导致上下文切换,比如,从硬件设备向内核监听的某个事件发送特定的信号,就会导致上下文切换,典型的例子就是鼠标的移动或键盘的按键

❓上下文切换是如何实现的?

  • Intel 80386 或更高的 cpu 保证对上下文切换的硬件支持
  • 大多数现代操作系统执行软件上下文切换(可以在任何 CPU 上使用),而不是硬件上下文切换,以获得更好的性能

🆚软件上下文切换的优缺点

  • 软件上下文切换的一个主要优点是:虽然硬件机制保存了几乎所有的 CPU 状态,但软件可以更具选择性,只保存实际需要保存和重新加载的部分
  • 使用软件上下文切换对于提高上下文切换的效率到底有多重要尚且未知

上下文的分类

在程序执行了系统调用或者触发某个异常(软中断),此时就会陷入内核空间,内核此时代表进程执行,并处于进程上下文

❓什么是进程上下文?

程序在执行过程中通常有用户态内核态两种状态,CPU 对处于内核态的进程根据上下文环境进一步细分,有如下三种状态:

  • 内核态,运行于进程上下文,内核代表进程运行于内核空间
  • 内核态,运行于中断上下文,内核代表硬件运行于内核空间
  • 用户态,运行于用户空间

用户空间的应用程序,通过系统调用,进入内核空间,这个时候用户空间的进程要传递很多变量、参数的值给内核,内核态运行的时候也要保存用户进程的一些寄存器值、变量等,进程上下文,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值以及当时环境

✨一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文

  • 用户级上下文: 正文、数据、用户堆栈以及共享存储区
  • 寄存器上下文: 通用寄存器、程序寄存器(PC)、处理器状态寄存器(EFLAGS)、栈指针(ESP)
  • 系统级上下文: 进程控制块 task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈

硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。所谓的“ 中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)。中断时,内核不代表任何进程运行,它一般只访问系统空间,而不会访问进程空间,内核在中断上下文中执行时一般不会阻塞

上下文切换的花费

✨上下文切换通常时计算密集型的,也就是说:它需要相当长的处理器时间,每秒需要做到数百次的上下文切换,额外花费非常多的时间降低了 CPU 的利用率

🎶就 CPU 时间而言,上下文切换对系统来说是一个巨大的成本,它可能是操作系统上成本最高的操作

上下文切换的成本在消耗 CPU 时间上一直在下降,但这似乎主要是由于 CPU 时钟速度的提高,而不是上下文切换本身效率的提高,与其他操作系统相比,Linux 的众多优势之一是它的上下文切换和模式切换成本极低

👴设计操作系统设计或高并发场景下,其中的一个主要焦点是:尽可能地避免不必要的上下文切换,然而,这在实践中并不容易做到

附录

从 Java 视角理解系统结构(一)CPU 上下文切换

Context Switch Definition

进程上下文与中断上下文