CPU上下文切换

CPU上下文

在每一个任务运行前,CPU 都须要知道任务从哪里加载、又从哪里开始运行,也就是说,须要系统事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC)。工具

CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,所以也被叫作 CPU 上下文。性能

CPU 上下文切换

  1. 就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来
  2. 加载新任务的上下文到这些寄存器和程序计数器
  3. 跳转到程序计数器所指的新位置,运行新任务。

根据任务的不一样,CPU 的上下文切换就能够分为几个不一样的场景,也就是进程上下文切换、线程上下文切换以及中断上下文切换。线程

进程和线程

进程是资源分配和执行的基本单位;线程是任务调度和运行的基本单位。线程没有资源,进程给指针提供虚拟内存、栈、变量等共享资源,而线程能够共享进程的资源。指针

进程上下文切换

Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间。
CPU 特权等级的 Ring 0 和 Ring 3。
内核空间(Ring 0)具备最高权限,能够直接访问全部资源;用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须经过系统调用陷入到内核中,才能访问这些特权资源。code

进程既能够在用户空间运行,又能够在内核空间中运行。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。从用户态到内核态的转变,须要经过系统调用来完成。队列

一次系统调用的过程,实际上是发生了两次 CPU 上下文切换。进程

线程上下文切换

线程的上下文切换其实就能够分为两种状况事件

  • 先后两个线程属于不一样进程。此时,由于资源不共享,因此切换过程就跟进程上下文切换是同样。
  • 先后两个线程属于同一个进程。此时,由于虚拟内存是共享的,因此在切换时,虚拟内存这些资源就保持不动,只须要切换线程的私有数据、寄存器等不共享的数据。

中断上下文切换

为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。而在打断其余进程时,就须要将进程当前的状态保存下来,这样在中断结束后,进程仍然能够从原来的状态恢复运行。内存

对同一个 CPU 来讲,中断处理比进程拥有更高的优先级,因此中断上下文切换并不会与进程上下文切换同时发生。一样道理,因为中断会打断正常进程的调度和执行,因此大部分中断处理程序都短小精悍,以便尽量快的执行结束。资源

中断只会发生在内核态

查看中断类型

从/proc/interrupts 这个只读文件中读取。/proc 其实是 Linux 的一个虚拟文件系统,用于内核空间与用户空间之间的通讯。/proc/interrupts 就是这种通讯机制的一部分,提供了一个只读的中断使用状况。

Vmstat

vmstat 是一个经常使用的系统性能分析工具,主要用来分析系统的内存使用状况,也经常使用来分析 CPU 上下文切换和中断的次数。

// 5s 输出间隔
[root@k8s ~]# vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 4  0      0 1150604 194172 2888576    0    0     4   238   77   35 61  3 36  0  0
 2  0      0 1147236 194172 2888812    0    0     0    96 3977 4630 69  4 27  0  0

cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。

Pidstat -w

pidstat给它加上 -w 选项,就能够查看每一个进程上下文切换的状况了。

// -w参数表示输出进程切换指标,而-u参数则表示输出CPU使用指标
// pidstat 默认显示进程的指标数据,加上 -t 参数后,才会输出线程的指标。
 pidstat 5 -w -u
Linux 3.10.0-1062.4.1.el7.x86_64 (instance-010oj085) 	04/04/2020 	_x86_64_	(2 CPU)

04:49:06 PM   UID       PID   cswch/s nvcswch/s  Command
04:49:11 PM     0         1      0.20      0.00  systemd
04:49:11 PM     0         6      1.20      0.00  ksoftirqd/0

cswch,表示每秒自愿上下文切换(voluntary context switches)的次数,nvcswch,表示每秒非自愿上下文切换(non voluntary context switches)的次数。

  • 所谓自愿上下文切换,是指进程没法获取所需资源,致使的上下文切换。好比说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
  • 而非自愿上下文切换,则是指进程因为时间片已到等缘由,被系统强制调度,进而发生的上下文切换。好比说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。

总结

  • CPU 上下文切换,是保证 Linux 系统正常工做的核心功能之一,通常状况下不须要咱们特别关注。
  • 但过多的上下文切换,会把 CPU 时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,致使系统的总体性能大幅降低。

上下文切换类型:

  • 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其余问题;
  • 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
  • 中断次数变多了,说明 CPU 被中断处理程序占用,还须要经过查看 /proc/interrupts 文件来分析具体的中断类型。
相关文章
相关标签/搜索