探討 Linux CPU 的上下文切換
眾所周知,Linux是一個支援多任務的作業系統,它能同時運行的任務數量遠遠超過CPU的數量。當然,這些任務其實並不是真正同時運作的(對於單一CPU),而是因為系統會在短時間內將CPU輪流分配給這些任務,從而創造出多個任務同時運作的假象。
CPU上下文(CPU Context)
在每個任務運行之前,CPU需要知道從哪裡載入和啟動該任務。這意味著系統需要提前設定好CPU的暫存器和程式計數器。
CPU暫存器是內建於CPU中的小型但非常快速的記憶體。而程式計數器用於儲存CPU目前正在執行的指令位置或下一條要執行的指令位置。
這兩者都是CPU在執行任何任務之前所必需的環境,因此被稱為」CPU上下文」。請參考下圖:

知道了 CPU 上下文是什麼,我想你理解 CPU 上下文切換就很容易了。 「CPU上下文切換」指的是先儲存上一個任務的 CPU 上下文(CPU暫存器和程式計數器),然後將新任務的上下文載入到這些暫存器和程式計數器中,最後跳到程式計數器。
這些已儲存的上下文儲存在系統核心中,並在重新安排任務執行時再次載入。這確保了任務的原始狀態不受影響,並且任務似乎持續運行。
CPU 上下文切換的類型
你可能會說 CPU 上下文切換無非就是更新 CPU 暫存器和程式計數器值,而這些暫存器是為了快速運行任務而設計的,那為什麼會影響 CPU 效能呢?
在回答這個問題之前,請問,你有沒有想過這些「任務」是什麼?你可能會說一個任務就是一個進程或一個線程。是的,進程和執行緒正是最常見的任務,但除此之外,還有其他類型的任務。
別忘了硬體中斷也是常見的任務,硬體觸發訊號,會引起中斷處理程序的呼叫。
因此,CPU 上下文切換至少有三種不同的類型:
- 進程上下文切換
- 線程上下文切換
- 中斷上下文切換
讓我們一一來看看。
進程上下文切換
#Linux 依照特權等級將行程的運作空間分割為核心空間和使用者空間,分別對應下圖中 Ring 0
和 Ring 3
的 CPU 特權等級的 。
-
核心空間(
Ring 0
)擁有最高權限,可以直接存取所有資源 -
使用者空間(
Ring 3
)只能存取受限資源,不能直接存取記憶體等硬體設備。它必須透過系統呼叫被陷入(trapped)核心中才能存取這些特權資源。

從另一個角度來看,一個行程既可以在使用者空間也可以在核心空間運作。當一個行程在使用者空間運行時,稱為該行程的使用者態,當它落入核心空間時,稱為該行程的內核狀態。
從用戶態到核心態的轉換需要透過系統呼叫來完成。例如,當我們查看一個檔案的內容時,我們需要以下系統呼叫:
-
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中文網其他相關文章!

學習Linux並不難。 1.Linux是一個開源操作系統,基於Unix,廣泛應用於服務器、嵌入式系統和個人電腦。 2.理解文件系統和權限管理是關鍵,文件系統是層次化的,權限包括讀、寫和執行。 3.包管理系統如apt和dnf使得軟件管理方便。 4.進程管理通過ps和top命令實現。 5.從基本命令如mkdir、cd、touch和nano開始學習,再嘗試高級用法如shell腳本和文本處理。 6.常見錯誤如權限問題可以通過sudo和chmod解決。 7.性能優化建議包括使用htop監控資源、清理不必要文件和使用sy

Linux管理員的平均年薪在美國為75,000至95,000美元,歐洲為40,000至60,000歐元。提升薪資可以通過:1.持續學習新技術,如雲計算和容器技術;2.積累項目經驗並建立Portfolio;3.建立職業網絡,拓展人脈。

Linux的主要用途包括:1.服務器操作系統,2.嵌入式系統,3.桌面操作系統,4.開發和測試環境。 Linux在這些領域表現出色,提供了穩定性、安全性和高效的開發工具。

互聯網運行不依賴單一操作系統,但Linux在其中扮演重要角色。 Linux廣泛應用於服務器和網絡設備,因其穩定性、安全性和可擴展性受歡迎。

Linux操作系統的核心是其命令行界面,通過命令行可以執行各種操作。 1.文件和目錄操作使用ls、cd、mkdir、rm等命令管理文件和目錄。 2.用戶和權限管理通過useradd、passwd、chmod等命令確保系統安全和資源分配。 3.進程管理使用ps、kill等命令監控和控制系統進程。 4.網絡操作包括ping、ifconfig、ssh等命令配置和管理網絡連接。 5.系統監控和維護通過top、df、du等命令了解系統運行狀態和資源使用情況。

介紹 Linux是一個強大的操作系統,由於其靈活性和效率,開發人員,系統管理員和電源用戶都喜歡。但是,經常使用長而復雜的命令可能是乏味的

Linux適用於服務器、開發環境和嵌入式系統。 1.作為服務器操作系統,Linux穩定高效,常用於部署高並發應用。 2.作為開發環境,Linux提供高效的命令行工具和包管理系統,提升開發效率。 3.在嵌入式系統中,Linux輕量且可定制,適合資源有限的環境。

簡介:通過基於Linux的道德黑客攻擊數字邊界 在我們越來越相互聯繫的世界中,網絡安全至關重要。 道德黑客入侵和滲透測試對於主動識別和減輕脆弱性至關重要


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

禪工作室 13.0.1
強大的PHP整合開發環境

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver CS6
視覺化網頁開發工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境