首頁  >  文章  >  系統教程  >  探討 Linux CPU 的上下文切換

探討 Linux CPU 的上下文切換

WBOY
WBOY轉載
2024-02-05 13:06:10625瀏覽

眾所周知,Linux是一個支援多任務的作業系統,它能同時運行的任務數量遠遠超過CPU的數量。當然,這些任務其實並不是真正同時運作的(對於單一CPU),而是因為系統會在短時間內將CPU輪流分配給這些任務,從而創造出多個任務同時運作的假象。

CPU上下文(CPU Context)

在每個任務運行之前,CPU需要知道從哪裡載入和啟動該任務。這意味著系統需要提前設定好CPU的暫存器程式計數器

CPU暫存器是內建於CPU中的小型但非常快速的記憶體。而程式計數器用於儲存CPU目前正在執行的指令位置或下一條要執行的指令位置。

這兩者都是CPU在執行任何任務之前所必需的環境,因此被稱為」CPU上下文」。請參考下圖:

探讨 Linux CPU 的上下文切换

知道了 CPU 上下文是什麼,我想你理解 CPU 上下文切換就很容易了。 「CPU上下文切換」指的是先儲存上一個任務的 CPU 上下文(CPU暫存器和程式計數器),然後將新任務的上下文載入到這些暫存器和程式計數器中,最後跳到程式計數器。

這些已儲存的上下文儲存在系統核心中,並在重新安排任務執行時再次載入。這確保了任務的原始狀態不受影響,並且任務似乎持續運行。

CPU 上下文切換的類型

你可能會說 CPU 上下文切換無非就是更新 CPU 暫存器和程式計數器值,而這些暫存器是為了快速運行任務而設計的,那為什麼會影響 CPU 效能呢?

在回答這個問題之前,請問,你有沒有想過這些「任務」是什麼?你可能會說一個任務就是一個進程或一個線程。是的,進程和執行緒正是最常見的任務,但除此之外,還有其他類型的任務。

別忘了硬體中斷也是常見的任務,硬體觸發訊號,會引起中斷處理程序的呼叫。

因此,CPU 上下文切換至少有三種不同的類型:

  • 進程上下文切換
  • 線程上下文切換
  • 中斷上下文切換

讓我們一一來看看。

進程上下文切換

#Linux 依照特權等級將行程的運作空間分割為核心空間和使用者空間,分別對應下圖中 Ring 0Ring 3 的 CPU 特權等級的 。

  • 核心空間Ring 0)擁有最高權限,可以直接存取所有資源
  • 使用者空間Ring 3)只能存取受限資源,不能直接存取記憶體等硬體設備。它必須透過系統呼叫陷入(trapped)核心中才能存取這些特權資源。
探讨 Linux CPU 的上下文切换

從另一個角度來看,一個行程既可以在使用者空間也可以在核心空間運作。當一個行程在使用者空間運行時,稱為該行程的使用者態,當它落入核心空間時,稱為該行程的內核狀態

用戶態核心態的轉換需要透過系統呼叫來完成。例如,當我們查看一個檔案的內容時,我們需要以下系統呼叫:

  • open():開啟檔案
  • read():讀取檔案的內容
  • write():將檔案的內容寫入到輸出檔案(包含標準輸出)
  • #close():關閉檔案

那麼在上述系統呼叫過程中是否會發生 CPU 上下文切換呢?當然是的。

這需要先保存 CPU 暫存器中原來的使用者狀態指令的位置。接下來,為了執行核心態的程式碼,需要將 CPU 暫存器更新到核心態指令的新位置。最後是跳到內核態運行內核任務。

那麼系統呼叫結束後,CPU 暫存器需要恢復原來儲存的使用者狀態,然後切換到使用者空間繼續運作進程。

因此,在一次系統呼叫的過程中,實際上有兩次 CPU 上下文切換。

但要指出的是,系統呼叫進程不會涉及進程切換,也不會涉及虛擬記憶體等系統資源切換。這與我們通常所說的「進程上下文切換」不同。進程上下文切換是指從一個進程切換到另一個進程,而係統呼叫期間始終運行同一個進程

系統呼叫過程通常被稱為特權模式切換,而不是上下文切換。但實際上,在系統呼叫過程中,CPU 的上下文切換也是不可避免的。

進程上下文切換 vs 系統呼叫

那麼進程上下文切換和系統呼叫有什麼差別呢?首先,進程是由核心管理的,進程切換只能發生在核心態。因此,進程上下文不僅包含虛擬記憶體堆疊全域變數等使用者空間資源,還包括核心堆疊暫存器等內核空間的狀態。

所以進程上下文切換系統呼叫要多出一步:

在儲存目前行程的核心狀態和 CPU 暫存器之前,需要先儲存行程的虛擬記憶體、堆疊等;並載入下一個行程的核心狀態。

根據 Tsuna 的測試報告,每次上下文切換需要數十奈秒至微秒的 CPU 時間。這個時間是相當可觀的,尤其是在大量進程上下文切換的情況下,很容易導致 CPU 花費大量時間來保存和恢復暫存器、核心堆疊、虛擬記憶體等資源。這正是我們在上一篇文章中談到的,一個導致平均負荷上升的重要因素。

那麼,該行程何時會被調度/切換到在 CPU 上運作?其實有很多場景,下面我要為大家總結一下:

  • When a process's CPU time slice runs out, it will be suspended by the system and switched to other processes waiting for the CPU to run.
  • When system resources are insufficient (such as insufficient memory), the process cannot run until resources are sufficient. At this time, the process will also be suspended, and the system will schedule other processes to run.
  • When a process automatically suspends itself through the sleep function, it will naturally be rescheduled.
  • When a process with a higher priority is running, in order to ensure the running of the high-priority process, the current process will be suspended by the high-priority process.
  • When a hardware interrupt occurs, the process on the CPU will be interrupted and suspended, and then execute the interrupt service routine in the kernel.

It is very necessary to understand these scenarios, because once there is a performance problem with context switching, they are the killer behind the scenes.

Thread context switching

The biggest difference between threads and processes is that threads are the basic unit of task scheduling, while processes are the basic unit of resource acquisition.

To put it bluntly, the so-called task scheduling in the kernel actually schedules threads; and the process only provides resources such as virtual memory and global variables for threads. Therefore, for threads and processes, we can understand it this way:

  • When a process has only one thread, it can be considered that one process is equal to one thread
  • When a process has multiple threads, these threads share the same resources, such as virtual memory and global variables.
  • In addition, threads also have their own private data, such as stacks and registers, which also need to be saved during context switches.

In this way, thread context switching can actually be divided into two situations:

  • First of all, the two threads before and after belong to different processes. At this time, since resources are not shared, the switching process is the same as process context switching.
  • Secondly, the two threads before and after belong to the same process. At this time, since the virtual memory is shared, the virtual memory resources remain unchanged during switching, and only the thread's private data, registers and other unshared data need to be switched.

Obviously, thread switching within the same process consumes less resources than switching multiple processes. This is also the advantage of multi-threading instead of multi-process.

Interrupt context switch

In addition to the previous two context switches, there is another scenario that also outputs CPU context switching, which is interrupt.

In order to quickly respond to events, hardware interrupts will interrupt the normal scheduling and execution process, and then call the interrupt handler.

When interrupting other processes, the current state of the process needs to be saved so that the process can still recover from the original state after the interruption.

Unlike process context, interrupt context switching does not involve the user state of the process. Therefore, even if the interrupt process interrupts the process in user mode, there is no need to save and restore user mode resources such as virtual memory and global variables of the process.

In addition, like process context switching, interrupt context switching will also consume CPU. Excessive switching times will consume a lot of CPU resources and even seriously reduce the overall performance of the system. Therefore, when you notice too many interrupts, you need to pay attention to check whether it will cause serious performance problems for your system.

in conclusion

In summary, no matter which scenario leads to context switching, you should know:

CPU context switching is one of the core functions to ensure the normal operation of the Linux system, and generally does not require our special attention.

However, excessive context switching will consume CPU time to save and restore data such as registers, kernel stacks, virtual memory, etc., thus shortening the actual running time of the process and causing a significant decrease in overall system performance.

以上是探討 Linux CPU 的上下文切換的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除