CPU上下文切換(上)

CPU上下文切換

​ 咱們常常說的平均負載和cpu升高沒有直接的關係,在不一樣的場景cpu升高會致使系統負載,可是系統負載不必定是cpu升高致使的。linux

1、系統負載太高的三種場景

  • cpu密集型進程,使用大量cpu會致使平均負載升高,此時這二者是一致的。
  • io密集型進程,等待io也會致使平均負載升高,但cpu不必定很高。緩存

  • 大量等待cpu的進程調度也會致使平均負載升高,此時cpu使用率也會比較高。

大量進程競爭cpu(也就是上面的第三個場景),每每是被忽略的,cpu雖然沒有使用,只是在競爭,也會發生負載嗎?微信

​ 咱們都知道linux是一個多任務操做系統,它支持遠大於cpu數量的任務同時運行,固然這些任務不是同時運行,而是系統在很短期內,將cpu輪流分配給它們,形成多任務同時運行的錯覺。而每一個任務運行前,cpu須要知道任務從哪裏加載、又從哪裏開始運行,也就是說,須要系統事先幫它設置好cpu寄存器和程序計數器多線程

2、CPU寄存器和程序計數器

1. cpu寄存器:

​ cpu內置的容量小、但速度極快的內存。ide

2. 程序計數器:

​ 是用來存儲cpu正在執行的指令位置、或者即將執行的下一條指令位置。他們都是cpu在運行任何任務前,必須的依賴環境,所以也被叫作cpu上下文。函數

3. cpu上下文切換

​ cpu上下文切換:就是先前一個任務的cpu上下文(也就是CPU寄存器和程序計數器)保存起來,而後加載新任務的上下文到這些寄存器和程序計數器,最後再跳轉到程序計數器所指的新位置,運行新任務。性能

​ 而這些保存下來的上下文,會存儲在系統內核中,並在任務從新調度執行時再次加載進來。這樣就保證原來任務的狀態不受影響,讓任務看起來仍是連續運行。操作系統

​ 根據任務不一樣,cpu的上下文切換就能夠分爲不一樣的幾個場景,進程上下文切換,線程上下文切換以及中斷上下文切換。線程

3.1. 進程上下文切換

​ linux安裝特權等級,把進程的運行空間分爲內核空間和用戶空間對象

![] 企業微信截圖_15486532103731.png

  • 內核空間(Ring0)具備最高權限,能夠直接訪問全部資源;

  • 用戶空間(Ring3)只能訪問受限權限,不能直接訪問內存等硬件設備,必須經過系統調用陷入到內核中,才能訪問特權資源。

​ 因此,進程既能夠在用戶空間運行又能夠在內核空間運行,在用戶空間運行時,稱爲用戶態。在內核空間運行時,稱爲內核態。

3.1.1. 系統調用是否發生cpu上下文切換
  • 系統調用:cpu寄存器裏面原來的用戶態的指令位置,須要先保存起來。接着,爲了執行內核態代碼,cpu寄存器須要更新爲內核態指令的新位置。最後,才跳轉到內核態運行內核任務。

  • 系統調用結束後:cpu寄存器須要恢復原來保存的用戶態,而後再切換到用戶空間,繼續運行進程。因此,一次系統調用,其實發送了兩次cpu上下文切換。
  • 系統調用過程當中,並不會涉及到虛擬內存等進程用戶態的資源,也不會切換進程。因此,系統調用一般稱爲特權模式切換,但實際上,系統調用也沒法避免cpu上下文切換。
3.1.2. 進程上下文切換跟系統調用區別

​ 進程是由內核來管理和調度的,進程的切換隻能發生在內核態,因此,進程的上下文不只包括了用戶態的虛擬內存,用戶棧,全局變量等資源。還包括了內核棧、寄存器等內核空間的狀態。

​ 所以,進程的切換比系統調用多了一步:在保存當前進程的內核狀態和cpu寄存器以前,須要先把用戶態的虛擬內存,用戶棧保存下來;在加載了下一進程的內核態後,須要刷新進程的虛擬內核和用戶棧。

​ 保存上下文和恢復上下文的進程並非免費的,須要內存在cpu上運行才能完成。

​ 每次上下文切換都須要幾十納秒到微妙的cpu時間。這個時間仍是至關可觀。在進程上下文切換次數較多的狀況下,很容易致使cpu將大量時間耗費在寄存器、內核棧以及虛擬內存等資源的保存和恢復上,進而大大縮短了真正運行進程的時間。這也是致使平均負載升高的重要因素。

​ linux經過(tlb)來管理虛擬內存和物理內存直接的映射關係,當虛擬內存更新後,tlb也要更新,內存訪問隨之變慢。特別是在多處理器系統上,緩存被多個處理器共享,刷新緩存不只影響當前處理器的進程,還會影響共享緩存的其餘處理器的進程。

3.1.3. 進程何時切換

​ 進程執行完終止了,會釋放cpu,這個時候cpu從就緒隊列裏面拿一個新的進程運行,還有其餘的一些非正常場景也會致使進程切換。

  • 時間片耗盡:爲了保證因此進程能夠獲得公平調度,CPU時間被劃分紅一段段的時間片,這些時間片輪流分配給各個進程。當某個時間片耗盡了,就會被系統掛起,切換到其餘等待cpu的進程運行。

  • 系統資源不足(如:內存不足):這個時候進程會被掛起,並由系統調度其餘進程運行。

  • 進程主動掛起: 當進程經過睡眠函數sleep這樣的方式將本身主動掛起時。

  • 高優先級進程:當有優先級高的進程出現時,爲了保證優先級高的進程運行,當前進程會被系統掛起

  • 硬件中斷時:當發生硬件中斷時,Cpu上的進程會被中斷掛起,轉而執行內核中的中斷服務程序。

    3.2. 線程上下文切換

    ​ 線程和進程最大的區別在於,線程是調度的基本單位,而進程則是資源擁有的基本單位。所謂內核中的任務調度,實際上的調度對象是線程;而進程只是給線程提供了虛擬內存、全局變量等資源。因此,對於線程和進程能夠理解爲:

  • 當進程只有一個線程時,能夠任務進程就是線程。

  • 當進程擁有多個線程時,這些線程共享相同的虛擬內存、全局變量等資源。這些資源在上下文切換時是不須要修改的。

  • 另外,線程也有本身的私有數據,如:棧和寄存器等,這些在上下文切換時也是須要保存的。

​ 因此說:

​ 當兩個線程不屬於同一進程時,線程上下文切換時。由於資源不共享,因此切換就至關於時進程間切換。

​ 當兩個線程屬於同一進程時,線程上下文切換時。由於資源共享,只須要切換線程私有數據。

​ 進程間切換消耗的資源多於線程間切換,因此就出現了多線程代替多進程的優點。

3.3. 中斷上下文切換

​ 爲了快速響應硬件的事件,中斷處理會打斷進程的正常調度和執行,轉而調用中斷處理程序,響應設備事件。在打斷其餘進程時,就須要將進程當前狀態保存起來。

​ 跟進程上下文切換不一樣是,中斷上下文切換不會涉及到進程的用戶態。因此,即使中斷過程打斷了一個用戶態的進程,也不須要保存和恢復進程的虛擬內存。全局變量等用戶態資源。中斷上下文,其實只包括內核態中斷服務程序執行必須的狀態,包括cpu寄存器、內核堆棧、硬件中斷參數等。

​ 對同一個cup來講,中斷處理比進程擁有更高的優先級,因此中斷上下文切換並不會與進程上線文切換同時發生。因此大部分中斷處理程序都短小精悍,以便儘快的執行結束。

總結

  1. cpu上下文切換,時保持Linux系統正常運行的核心功能之一,通常狀況不須要咱們特別關注。
  2. 過多的上下文切換,會把cpu時間消耗在寄存器、內核棧以及虛擬內存等數據的保存和恢復上,從而縮短了進程真正運行的時間,致使系統性能降低。
相關文章
相關標籤/搜索