cpu的用戶態和內核態和內存的用戶空間內核空間


談到CPU的這兩個工作狀態,也就是處理器的這兩個工作狀態,那我們有必要說一下為什么搞出這兩個鬼玩意出來。
       用過電腦的娃娃們肯定知道在一個系統中既有操作系統的程序,也由普通用戶的程序。但那么多指令,可不是隨便亂用的,有些指令只能由系統來使用,禁止用戶程序去直接訪問。為了保證操作系統和各個應用程序能夠順利運行,就必須對他們進行限制,否則的話就根本沒有辦法保證系統的安全性和穩定。
       所以呢,根據運行程序對資源和機器指令的使用權限,把處理器設置為不同的狀態。多數系統把處理器的工作狀態分為管態和目態兩種。也就是我們今天要說的這兩個東西。
       所謂管態,即操作系統的管理程序運行時的狀態,它具有較高的特權級別,也稱為特權態、系統態、內核態或者核心態。當處理器處於管態時,他可以執行所有的指令,包括各種特權指令,也可以使用所有的資源,並且具有改變處理器狀態的能力,是感覺很牛逼。需要指出的是,管態和超級用戶不同,前者是指CPU的狀態,后者是指一種特殊的計算機用戶;前者主要是從硬件的角度去執行任何指令,而后者是從軟件的角度來管理系統的軟硬件資源,如用戶賬戶、權限管理、文件訪問等。超級用戶執行的程序不一定運行在管態,而管態程序也不一定由系統管理員啟動,普通用戶也可以啟動。
       所謂目態,即用戶程序運行時的狀態,它具有較低的特權級別,又稱為普通態或用戶態。在這種狀態下不能使用特權指令,不能直接使用系統資源,也不能改變CPU的工作狀態,並且只能訪問這個用戶程序自己的存儲空間。用戶態不允許程序進行處理器中要求特權態的操作,以避免操作系統崩潰。每個進程都在各自的用戶空間中運行,而不允許存取其他程序的用戶空間。
         百度百科上的這個圖片對於這兩個狀態划分就挺好的。
CPU的兩種工作狀態:內核態和用戶態(或者稱管態和目態)
      當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(或簡稱為內核態)。此時處理器處於特權級最高的(0級)內核 代碼中執行。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。當進程在執行用戶自己的代碼時,則稱其處於用戶運行 態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。
       在內核態下CPU可執行任何指令,在用戶態下CPU只能執行非特權指令。當CPU處於內核態,可以隨意進入用戶態;而當CPU處於用戶態時,用 戶從用戶態切換到內核態只有在系統調用和中斷兩種情況下發生,一般程序一開始都是運行於用戶態,當程序需要使用系統資源時,就必須通過調用軟中斷進入內核 態。   
       Linux使用了Ring3級別運行用戶態,Ring0作為內核態,沒有使用Ring1和Ring2。Ring3狀態不能訪問Ring0的地址 空間,包括代碼和數據。Linux進程的4GB地址空間,3G-4G部分大家是共享的,是內核態的地址空間,這里存放在整個內核的代碼和所有的內核模塊, 以及內核所維護的數據。用戶運行一個程序,該程序所創建的進程開始是運行在用戶態的,如果要執行文件操作,網絡數據發送等操作,必須通過 write,send等系統調用,這些系統調用會調用內核中的代碼來完成操作,這時,必須切換到Ring0,然后進入3GB-4GB中的內核地址空間去執 行這些代碼完成操作,完成后,切換回Ring3,回到用戶態。這樣,用戶態的程序就不能隨意操作內核地址空間,具有一定的安全保護作用。
       我在網易的一篇博客中看到一個解釋挺好的一個文章,對方是從一段實例中開始的,所以我粘貼過來分享了一下:

1. 用戶態和內核態的概念區別

究竟什么是用戶態,什么是內核態,這兩個基本概念以前一直理解得不是很清楚,根本原因個人覺得是在於因為大部分時候我們在寫程序時關注的重點和着眼的角度放在了實現的功能和代碼的邏輯性上,先看一個例子:

1)例子

C代碼
  1. void testfork(){  
  2. if(0 = = fork()){  
  3. printf(“create new process success!\n”);  
  4. }  
  5. printf(“testfork ok\n”);  
  6. }  
 

這 段代碼很簡單,從功能的角度來看,就是實際執行了一個fork(),生成一個 新的進程,從邏輯的角度看,就是判斷了如果fork()返回的是0則打印相關語句,然后函數最后再打印一句表示執行完整個testfork()函數。代碼 的執行邏輯和功能上看就是如此簡單,一共四行代碼,從上到下一句一句執行而已,完全看不出來哪里有體現出用戶態和進程態的概念。

如果說前面兩種是靜態觀察的角度看的話,我們還可以從動態的角度來看這段代碼,即它被轉換成CPU執行的指令后加載執行的過程,這時這段程序就是一個動態執行的指令序列。而究竟加載了哪些代碼,如何加載就是和操作系統密切相關了。

2)特權級

熟 悉Unix/Linux系統的人都知道,fork的工作實際上是以系統調用的 方式完成相應功能的,具體的工作是由sys_fork負責實施。其實無論是不是Unix或者Linux,對於任何操作系統來說,創建一個新的進程都是屬於 核心功能,因為它要做很多底層細致地工作,消耗系統的物理資源,比如分配物理內存,從父進程拷貝相關信息,拷貝設置頁目錄頁表等等,這些顯然不能隨便讓哪 個程序就能去做,於是就自然引出特權級別的概念,顯然,最關鍵性的權力必須由高特權級的程序來執行,這樣才可以做到集中管理,減少有限資源的訪問和使用沖 突。

特權級顯然是非常有效的管理和控制程序執行的手 段,因此在硬件上對特權級做了很 多支持,就Intel x86架構的CPU來說一共有0~3四個特權級,0級最高,3級最低,硬件上在執行每條指令時都會對指令所具有的特權級做相應的檢查,相關的概念有 CPL、DPL和RPL,這里不再過多闡述。硬件已經提供了一套特權級使用的相關機制,軟件自然就是好好利用的問題,這屬於操作系統要做的事情,對於 Unix/Linux來說,只使用了0級特權級和3級特權級。也就是說在Unix/Linux系統中,一條工作在0級特權級的指令具有了CPU能提供的最 高權力,而一條工作在3級特權級的指令具有CPU提供的最低或者說最基本權力。

3)用戶態和內核態

現 在我們從特權級的調度來理解用戶態和內核態就比較好理解了,當程序運行在3級 特權級上時,就可以稱之為運行在用戶態,因為這是最低特權級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態;反之,當程序運 行在0級特權級上時,就可以稱之為運行在內核態。

雖 然用戶態下和內核態下工作的程序有很多差別,但最重要的差別就在於特權級的不 同,即權力的不同。運行在用戶態下的程序不能直接訪問操作系統內核數據結構和程序,比如上面例子中的testfork()就不能直接調用 sys_fork(),因為前者是工作在用戶態,屬於用戶態程序,而sys_fork()是工作在內核態,屬於內核態程序。

當 我們在系統中執行一個程序時,大部分時間是運行在用戶態下的,在其需要操作系 統幫助完成某些它沒有權力和能力完成的工作時就會切換到內核態,比如testfork()最初運行在用戶態進程下,當它調用fork()最終觸發 sys_fork()的執行時,就切換到了內核態。

2. 用戶態和內核態的轉換

1)用戶態切換到內核態的3種方式

a. 系統調用

這 是用戶態進程主動要求切換到內核態的一種方式,用戶態進程通過系統調用申請使 用操作系統提供的服務程序完成工作,比如前例中fork()實際上就是執行了一個創建新進程的系統調用。而系統調用的機制其核心還是使用了操作系統為用戶 特別開放的一個中斷來實現,例如Linux的int 80h中斷。

b. 異常

當CPU在執行運行在用戶態下的程序時,發生了某些事先不可知的異常,這時會觸發由當前運行進程切換到處理此異常的內核相關程序中,也就轉到了內核態,比如缺頁異常。

c. 外圍設備的中斷

當 外圍設備完成用戶請求的操作后,會向CPU發出相應的中斷信號,這時CPU會 暫停執行下一條即將要執行的指令轉而去執行與中斷信號對應的處理程序,如果先前執行的指令是用戶態下的程序,那么這個轉換的過程自然也就發生了由用戶態到 內核態的切換。比如硬盤讀寫操作完成,系統會切換到硬盤讀寫的中斷處理程序中執行后續操作等。

這3種方式是系統在運行時由用戶態轉到內核態的最主要方式,其中系統調用可以認為是用戶進程主動發起的,異常和外圍設備中斷則是被動的。

2)具體的切換操作

從 觸發方式上看,可以認為存在前述3種不同的類型,但是從最終實際完成由用戶態 到內核態的切換操作上來說,涉及的關鍵步驟是完全一致的,沒有任何區別,都相當於執行了一個中斷響應的過程,因為系統調用實際上最終是中斷機制實現的,而 異常和中斷的處理機制基本上也是一致的,關於它們的具體區別這里不再贅述。關於中斷處理機制的細節和步驟這里也不做過多分析,涉及到由用戶態切換到內核態 的步驟主要包括:

[1] 從當前進程的描述符中提取其內核棧的ss0及esp0信息。

[2] 使用ss0和esp0指向的內核棧將當前進程的cs,eip,eflags,ss,esp信息保存起來,這個

過程也完成了由用戶棧到內核棧的切換過程,同時保存了被暫停執行的程序的下一

條指令。

[3] 將先前由中斷向量檢索得到的中斷處理程序的cs,eip信息裝入相應的寄存器,開始

執行中斷處理程序,這時就轉到了內核態的程序執行了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM