CPU寄存器,與程序計數器(存儲CPU正在執行的指令位置,或者即將執行的下一條指令的位置)共同組成CPU上下文。
CPU上下文切換指的是:把前一個任務的CPU上下文保存起來,然后加載新任務的上下文到這些寄存器和程序計數器上,最后再跳轉到程序計數器所指的新位置,運行新的任務。被保存下來的上下文會存儲在系統內核中,等任務重新調度執行時再次加載進來。
根據任務的不同,CPU的上下文切換可以分為幾個不同場景(進程上下文切換、線程上下文切換、中斷上下文切換)
進程上下文切換
系統調用:
已知進程運行空間分為內核空間和用戶空間。內核空間可以訪問所有資源,用戶空間只能訪問受限資源,不能訪問內存等硬件設備。
從用戶態到內核態的轉變需要通過系統調用來完成。如open、read、write、close
等對于文件的操作都屬于系統調用。
系統調用的過程中會發生CPU上下文切換,先切換到內核態,執行內核態代碼,再跳轉回用戶態代碼。所以一次系統調用會發生兩次CPU上下文切換,又稱特權模式切換,不過仍然是同一個進程在運行。
進程上下文切換性能問題:
進程由內核管理和調度,進程的切換只能發生在內核態,進程上下文不僅包括虛擬內存、棧、全局變量等用戶空間資源,還包括內核堆棧、寄存器等內核空間狀態。每次進程上下文切換需要幾十納秒到數微秒的CPU時間。
并且Linux通過TLB來管理虛擬內存到物理內存之間的映射,當虛擬內存更新后,TLB也需要刷新,內存的訪問也會隨之變慢。特別在多處理器系統上,緩存被多個處理器共享,刷新緩存不僅會影響當前處理器的進程,還會影響共享緩存的其他處理器的進程。
進程上下文切換發生的時機:
在進程調度的時候,需要進行切換上下文。Linux為每個CPU維護一個就緒隊列,將活躍進程(正在運行和正在等待CPU的進程)
按照優先級和等待CPU的時間來排序,然后選擇最需要CPU的進程運行。(優先級高和等待時間長的進程)
1、CPU時間被劃分為一段段時間片,當某個進程的時間片耗盡,就會被系統掛起,切換到其他正在等待的進程
2、進程在系統資源不足時,要等到資源滿足后才可以運行,此時這個進程也會被掛起,CPU讓給其他進程
3、進程通過sleep睡眠函數主動掛起,CPU讓給其他進程
4、當有優先級更高的進程運行,當前進程會被掛起
5、發生硬件中斷,CPU進程會被中斷掛起,執行內核中的中斷服務程序
進程上下文切換
線程是調度的基本單位,而進程是資源擁有的基本單位。當進程中只有一個線程時,可以認為進程就等于線程。
當進程擁有多個線程時,這些線程會共享相同的虛擬內存和全局變量等資源。
線程主要就是私有數據、棧和寄存器等資源。
線程上下文切換分為兩種情況:
1、兩個線程屬于不同線程,資源不共享,所以等同于進程上下文切換
2、兩個線程屬于同一個進程,只需要切換私有數據、寄存器等不共享的數據
中斷上下文切換
與系統調用不同,中斷上下文切換不涉及進程的用戶態。所以中斷過程打斷了一個正處于用戶態的進程,也不需要保存和恢復這個進程的虛擬內存、全局變量等用戶資源。它只包括內核態中斷服務程序執行所必須的狀態:CPU寄存器、內核堆棧、硬件中斷參數