用戶態和內核態的區別是啥
這篇文章的深度不會太深,重點就是了解一下用戶態和內核態的區別就 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 正在執行什麼級別的指令
知道了用戶態和內核態的區別、以及為什麼要對其進行區別之後,我們就可以來看什麼時候會從用戶態切換到內核態了。
答案是發生系統調用的時候
那什麼又是系統調用呢?看這張圖

當用戶態的程式需要向作業系統申請更高許可權的服務時,就通過系統調用向內核發起請求。
內核自然也會提供很多的介面來供調用,例如申請動態記憶體空間。但是申請了記憶體是不是還得考慮釋放記憶體?如果把這塊記憶體管理交給應用程式的話,複雜的管理工作會給開發帶來很多負擔。
所以庫函數就是用於屏蔽掉內部複雜的細節的,我們的應用程式可以通過庫函數來調用內核的提供的介面,而庫函數就會發起系統調用,發起了系統調用之後,用戶態就會切換成內核態去執行對應的內核方法。
除了系統調用之外,還有另外兩種會導致態的切換:發生異常、中斷。
本篇文章已放到我的 Github github.com/sh-blog 中,歡迎 Star。微信搜索關注【SH的全棧筆記】,回復【隊列】獲取MQ學習資料,包含基礎概念解析和RocketMQ詳細的源碼解析,持續更新中。
如果你覺得這篇文章對你有幫助,還麻煩點個贊,關個注,分個享,留個言。
