一、特權級
Intel x86架構的cpu一共有0~4四個特權級,0級最高,3級最低,硬件上在執行每條指令時都會對指令所具備的特權級作相應的檢查。硬件已經提供了一套特權級使用的相關機制,軟件天然要好好利用,這屬於操做系統要作的事情,
對於UNIX/LINUX來講,只使用了0級特權級別和3級特權級。也就是說在UNIX/LINUX系統中,一條工做在0級特權級的指令具備了CPU能提供的最高權力,而一條工做在3級特權的指令具備CPU提供的最低或者說最基本權力
二、用戶態和內核態
內核棧:Linux中每一個進程有兩個棧,分別用於用戶態和內核態的進程執行,其中的內核棧就是用於內核態的堆棧,它和進程的task_struct結構,更具體的是thread_info結構一塊兒放在兩個連續的頁框大小的空間內。
如今咱們從特權級的調度來理解用戶態和內核態就比較好理解了,
當程序運行在3級特權級上時,就能夠稱之爲運行在用戶態,由於這是最低特權級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態;反之,當程序運行在0級特權級上時,就能夠稱之爲運行在內核態。
雖然用戶態下和內核態下工做的程序有不少差異,但最重要的差異就在於特權級的不一樣,即權力的不一樣。運行在用戶態的程序不能訪問操做系統內核數據結構合程序。 當咱們在系統中執行一個程序時,大部分時間是運行在用戶態下的。在其須要操做系統幫助完成某些它沒有權力和能力完成的工做時就會切換到內核態。
Linux進程的4GB地址空間,3G-4G部分你們是共享的,是內核態的地址空間,這裏存放在整個內核的代碼和全部的內核模塊,以及內核所維護的數據。
用戶運行一個程序,該程序所建立的進程開始是運行在用戶態的,若是要執行文件操做,網絡數據發送等操做,必須經過write,send等系統調用,這些系統調用會調用內核中的代碼來完成操做,這時,必須切換到Ring0,而後進入3GB-4GB中的內核地址空間去執行這些代碼完成操做,完成後,切換回Ring3,回到用戶態。這樣,用戶態的程序就不能隨意操做內核地址空間,具備必定的安全保護做用。
保護模式,經過內存頁表操做等機制,保證進程間的地址空間不會互相沖突,一個進程的操做不會修改另外一個進程的地址空間中的數據。
在內核態下,CPU可執行任何指令,在用戶態下CPU只能執行非特權指令。當CPU處於內核態,能夠隨意進入用戶態;而當CPU處於用戶態,只能經過中斷的方式進入內核態。通常程序一開始都是運行於用戶態,當程序須要使用系統資源時,就必須經過調用軟中斷進入內核態.
三、用戶態和內核態的轉換
1)用戶態切換到內核態的3種方式
a. 系統調用
這是用戶態進程主動要求切換到內核態的一種方式,用戶態進程經過系統調用申請使用操做系統提供的服務程序完成工做。而系統調用的機制,其核心仍是使用了操做系統爲用戶特別開放的一箇中斷來實現,例如lx86的int 80h, powerpc的sc
b. 異常
當CPU在執行運行在用戶態下的程序時,發生了某些事先不可知的異常,這時會觸發由當前運行進程切換處處理此異常的內核相關的程序中,也就是轉到了內核態,好比缺頁異常。
c. 外圍設備的中斷
當外圍設備完成用戶請求的操做後,會向CPU發出相應的中斷信號,這時CPU會暫停執行下一條即將要執行的指令轉而去執行與中斷信號對應的處理程序,若是先前執行的指令是用戶態下的程序,那麼這個轉換的過程天然也就發生了由用戶態到內核態的切換。好比硬盤讀寫操做的完成,系統會切換到硬盤讀寫的中斷處理程序中執行後續操做等。
這3種方式是系統在運行時由用戶態轉到內核態的最主要方式,其中系統調用能夠認爲是用戶進程主動發起的,異常和外圍中斷是被動的。
四、具體的切換操做
從觸發方式上看,能夠認爲純在前述3種不一樣的類型,可是從最終實際完成由用戶態到內核態的切換操做上來講,涉及的關鍵步驟是徹底一致的,沒有任何區別,都至關於執行了一箇中斷響應的過程,由於系統調用實際上最終是中斷機制實現的,而異常和中斷的處理機制基本上也是一致的。關於中斷處理機制的細節合步驟這裏不作過多分析,涉及到有用戶態切換到內核態的步驟主要包括:
【1】從當前進程的描述符中提取其內核棧的ss0及esp0信息
【2】使用ss0和esp0指向的內核棧將當前進程的cs,eip,eflags,ss,esp信息保存起來,這個過程也完成了由用戶棧到內核棧的切換過程,同時保存了被暫停執行的程序的下一條指令。
【3】將先前又中斷向量檢索獲得的中斷處理程序的cs,eip信息裝入相應的寄存器,開始執行中斷處理程序,這時就轉到內核態的程序執行了。