深入理解作業系統中程式與執行緒的區別及切換機制(上)

努力的小雨發表於2023-08-28

程式

所謂程式,大家可以理解為我們開啟的應用程式,如微信、QQ、遊戲等,但也有系統應用是我們看不見的,可以開啟工作管理員一探究竟,我們寫的程式碼程式在伺服器上在不執行的情況下,它就是一個二進位制檔案,並不是程式!

image

一個程式可以包含一個或者多個執行緒,但對於CPU來說他就是一個任務而已;

image

在早期,我們的CPU只有一個,而有多個任務需要執行時,它們只能排隊等待,無論前面的任務執行時間有多長,後面的任務都得耐心等待。這種方式顯然存在明顯的弊端。舉個例子,假設排在前面的A任務需要執行1小時,而排在後面的B任務僅需1分鐘,那麼B任務必須等待A任務完成後才能執行,這種方式顯得極其不靈活。

進一步發展後,我們擁有了多工的系統。在CPU在同一時間只能處理一個任務的前提下,系統將時間劃分為多個時間片,每個任務只能佔用一個時間片來執行自己的任務。一旦時間片用完,就必須輪到下一個任務執行,這種方式看起來就像是多個程式或任務同時在執行,這就是我們所說的併發,也稱為偽並行。

有偽並行,那麼就有真並行,隨著現代化發展,我們的CPU開始擁有多核處理器,如4核、8核等。這樣每個核心就像一個獨立的CPU一樣,可以並行處理多個任務。,8核對應的就是8個任務並行處理;

image

然而,我們當前的伺服器系統都是高併發狀態,不僅要執行自己的業務,還要佔用一定的CPU資源來執行系統程式。因此,以下一系列問題就出現了:

  1. 一個任務佔用多長時間的時間片?
  2. CPU如何進行任務切換?當一個任務正在執行時被切換,資源如何處理?
  3. CPU如何找到下一個要執行的任務的位置?

程式的狀態

五狀態模型

image

當我們的程式啟動後就會變成這種狀態,關聯如下:

就緒->執行:當任務獲得時間片後,使用CPU執行操作,進入執行狀態。

執行->阻塞:程式呼叫系統服務時,無法立即獲取返回值(如IO操作),進入阻塞狀態。

執行->就緒:如果佔用的時間片已經結束了,但任務未完成,回到就緒狀態。

阻塞->就緒:阻塞結束後,程式回到就緒狀態。

執行->結束:程式自行完成任務後,那麼會被系統終止;

以上便是對於單個程式的5狀態描述,從上面可以看出由於系統通常同時執行多個程式,因此就緒和阻塞狀態的程式可能會有多個,那麼這麼多進行都在就緒態和阻塞態怎麼辦?一般來說就是使用佇列,這不跟你寫java是一樣的解決方案嗎?排隊就行了

七狀態模型

image

佇列是可以解決排隊了問題了,但是這麼長的佇列放到哪裡呢?我們的記憶體是很寶貴的,所以這裡面就有上一節說的記憶體交換的問題了,可以使用記憶體交換機制將部分程式交換到磁碟中,這時候就是一個掛起的狀態;

掛起的狀態分兩種:

  1. 就緒狀態的掛起:一旦程式重新載入到記憶體中,就會立即執行。
  2. 阻塞狀態的掛起:等待特定事件發生後才會執行。

這時候你就知道為什麼你可以執行很多個程式,但是有時候你開啟的太多了,你正開啟某一個軟體的同時,另一個軟體自己退了,你就可以看下你的記憶體是不是滿了,這是因為已經被交換到磁碟中的程式不容易重新載入回記憶體。一旦記憶體已滿,重新載入程式就變得困難。

總結

程式是指正在執行的程式,可以包含一個或多個執行緒。在早期,CPU只有一個核心,多個任務需要排隊等待執行。後來,引入了多工的概念,將時間劃分為多個時間片,每個任務佔用一個時間片執行,實現了偽並行。現代CPU擁有多核處理器,可以並行處理多個任務。高併發的伺服器系統中,除了執行業務,還要佔用一定的CPU資源執行系統程式。程式的狀態透過佇列進行管理。同時還討論了記憶體交換和程式掛起的問題。

相關文章