使用者態和核心態的區別是啥

detectiveHLH發表於2021-12-20

這篇文章的深度不會太深,重點就是了解一下使用者態和核心態的區別就 OK 了。

先給不瞭解核心態、使用者態的簡單介紹一下,我們在什麼時候會提到這兩個概念。

例如我們的應用程式需要從磁碟讀取某個檔案的資料,此時並不是直接從磁碟載入到應用記憶體中,而是:

  • 先將資料從「磁碟」複製到「核心 Buffer」
  • 再將資料從「核心 Buffer」複製到「使用者 Buffer」

以上就是使用者態核心態的概念。首先我們給他下個定義,這兩個是作業系統的執行級別

然後我們知道,我們寫的程式,最終執行的時候實際都會被編譯、解釋成一條一條的 CPU 指令被 CPU 執行。

解釋成一條一條的指令
解釋成一條一條的指令

使用者態、核心態的指令都是 CPU 都在執行,所以我們可以換個說法,實際上這個態代表的是當前 CPU 的狀態。那既然這些指令最終都由 CPU 執行,那對其區分的理由是什麼呢?

那是因為,CPU 指令根據其重要的程度,也分為不同的許可權。有一些指令執行失敗了無關痛癢,而有一些指令失敗了會導致整個作業系統崩潰,甚至需要重啟系統。如果將這些指令隨意開放給應用程式的話,整個系統崩潰的概率將會大大的增加。

再舉個類似的例子。我們設計一個類,裡面有幾個很重要的變數,你大概率是不會把它們宣告成 public 的吧?應該宣告成 private,並開發幾個專門修改他們的方法,對傳入的值進行一系列的校驗之後再去設定。

上面說到,CPU 指令是做了許可權劃分的, 例如 Intel X86 中將 CPU 指令許可權劃分為了 4 個等級:

許可權分類
許可權分類

它們之間的許可權的高低程度可以通過這張圖來識別:

圖片來源於網路,侵刪
圖片來源於網路,侵刪

上圖中的 IA 指的是 Intel Architecture

所以可以看到,越靠近的核心的許可權越高。換句話說,許可權由高到低為:Ring0 > Ring1 > Ring2 > Ring3

在 Linux 系統中,由於只有 Ring0 和 Ring3 級別的指令,所以我們可以對使用者態、核心態給一個更細節的區別描述:執行 Ring0 級別指令的叫核心態,執行 Ring3 級別指令的叫使用者態

核心態使用者態
核心態使用者態

瞭解了指令集許可權的概念,我們就可以再更正一下上面的描述:什麼實際上代表的是當前 CPU 正在執行什麼級別的指令

知道了使用者態和核心態的區別、以及為什麼要對其進行區別之後,我們就可以來看什麼時候會從使用者態切換到核心態了。

答案是發生系統呼叫的時候

那什麼又是系統呼叫呢?看這張圖

系統呼叫 (1)
系統呼叫 (1)

當使用者態的程式需要向作業系統申請更高許可權的服務時,就通過系統呼叫向核心發起請求。

核心自然也會提供很多的介面來供呼叫,例如申請動態記憶體空間。但是申請了記憶體是不是還得考慮釋放記憶體?如果把這塊記憶體管理交給應用程式的話,複雜的管理工作會給開發帶來很多負擔。

所以庫函式就是用於遮蔽掉內部複雜的細節的,我們的應用程式可以通過庫函式來呼叫核心的提供的介面,而庫函式就會發起系統呼叫,發起了系統呼叫之後,使用者態就會切換成核心態去執行對應的核心方法。

除了系統呼叫之外,還有另外兩種會導致態的切換:發生異常、中斷。

本篇文章已放到我的 Github github.com/sh-blog 中,歡迎 Star。微信搜尋關注【SH的全棧筆記】,回覆【佇列】獲取MQ學習資料,包含基礎概念解析和RocketMQ詳細的原始碼解析,持續更新中。

如果你覺得這篇文章對你有幫助,還麻煩點個贊關個注分個享留個言

相關文章