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 文件來分析具體的中斷類型。
相關文章
相關標籤/搜索