所有的現代操作系統中,CPU是在兩種不同的模式下運行的:


注意以下內容來自微軟:
windows用戶模式和內核模式
運行 Windows 的計算機中的處理器有兩個不同模式:用戶模式 和內核模式 。
用戶模式和內核模式都是針對CPU運行狀態來說的,在用戶模式下,CPU無法執行一些特權指令,而在內核模式下是可以的。
根據處理器上運行的代碼的類型,處理器在兩個模式之間切換。 應用程序在用戶模式下運行,核心操作系統組件在內核模式下運行。 雖然許多驅動程序以內核模式運行,但某些驅動程序可能以用戶模式運行。
R3 用戶態 所有api都通過ntdll調用到內核Api
上面所說的兩種模式不僅僅是字面上的區別,它們是受CPU嚴格制約的。如果在用戶模式下,程序嘗試做些其權限以外的事情,比如說,執行一條高權限的CPU指令,修改其被禁止訪問的內存,這時一個可捕獲的異常就會拋出。但這只會導致這個倒霉的應用程序崩潰,而不會讓你的整個系統崩潰。這就是用戶模式的意義所在。
x86 CPU提供4種保護層級: 0, 1, 2 and 3. 實際上,只用0級(內核)和3級(用戶程序)被使用到了
用戶模式
啟動用戶模式應用程序時,Windows 會為該應用程序創建進程 。 進程為應用程序提供專用的虛擬地址空間和專用的句柄表 。 由於應用程序的虛擬地址空間為專用空間,因此一個應用程序無法更改屬於其他應用程序的數據。 每個應用程序都隔離運行,如果一個應用程序發生故障,則故障僅局限於該應用程序。 其他應用程序和操作系統不會受該故障的影響。
除了專用之外,用戶模式應用程序的虛擬地址空間也受到限制。 在用戶模式下運行的處理器無法訪問為操作系統保留的虛擬地址。 限制用戶模式應用程序的虛擬地址空間可防止應用程序更改以及可能損壞關鍵的操作系統數據。
內核模式
在內核模式下運行的所有代碼都共享單個虛擬地址空間。 這意味着內核模式驅動程序不會與其他驅動程序和操作系統本身隔離。 如果內核模式驅動程序意外寫入錯誤的虛擬地址,則屬於操作系統或其他驅動程序的數據可能會受到安全威脅。 如果內核模式驅動程序發生故障,整個操作系統就會發生故障。
此圖說明了用戶模式組件與內核模式組件之間的通信。

以上內容來源:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/user-mode-and-kernel-mode


以下是內核的層次划分:
1、硬件抽象層(HardwareAbstraction Layer) (HAL) (hal.dll)
最底層隔離硬件的,底層的第三方驅動程序就執行在這層。
2、內核(Kernel)
實現操作系統的一些底層服務。比方線程調度,多處理器的同步,中斷/異常處理等。
3、運行體(Executive)(ntoskrnl.exe)
實現主要的操作系統服務,比方主要的線程進程管理,內存管理, IO及進程間通訊等。
4、窗體圖形子系統(Windows Graphics Subsystem)
由win32K.sys在內核層實現,用戶界面相關都依賴該層,User32.dll的大部分功能都由該層實現
用戶層關鍵進程
Windows系統在用戶層有幾個關鍵的系統進程:
Smss.exe(session manager Subsystem)
關於Session的概念能夠參考我的這篇Sessions, Window Stationsand Desktops。在操作系統啟動時會創建一個不與不論什么Session關聯的Smss.exe管理者實例。然后當實用戶登錄時它會為每一個Sessin拷貝一份與之關聯的Smss.exe實例,然后由該關聯的Smss.exe實例啟動winlogon.exe和csrss.exe.
WinLogon.exe
該進程管理用戶的登錄和注銷,我們按Ctrl+Alt+Del出現的界面和登錄后出現的桌面窗體都是由它啟動的。
Csrss.exe( Client/Server Runtime Subsystem)
我們能夠看到我們的桌面窗體(GetDesktopWindow)是由該進程創建的,該進程主要負責Win32子系統的用戶模式部分(內核模式部分由win32k.sys實現)。
Lsass.exe(Local Security Authority Subsystem)
WinLogon.exe通過該進程驗證用戶登錄,登錄后產生安全訪問令牌對象。通過該令牌創建Explorer.exe,我們其它用戶進程都由Explorer.exe啟動。而且繼承了該令牌權限。
Services.exe
該進程簡稱為SCM(NT Service Control Manager),該進程負責啟動用戶態一些特殊進程。也就是我們通常所說的服務程序。
3、用戶模式調用內核模式的方式
4、內核模式調用用戶模式
能夠通過IOCTL的上下文傳遞,也能夠通過APC (Asynchronous Procedure Call)直接調用。
5、進程間的通信
第二種很強大的用戶模式與內核模式通訊方式,同一時候也支持進程間通訊,該方式就是ALPC(Advanced Local Procedure Call)。該方式被操作系統大量使用。 WinRT中的Broker進程也用到了它。
該方式實際上就4個核心函數:nt!NtAlpcSendWaitReceivePort,nt!NtAlpcCreatePort, nt!NtAlpcConnectPort, Nt!AplcAcceptConnectPort, 大概原理例如以下:
在多任務環境中,有許多進程都不允許應用程序去做。所以CPU以兩種模式運行,即用戶模式和內核模式。
①內核模式
當CPU運行於內核模式時,一切程序都可運行。任務可以執行特權級指令,對任何I/O設備有全部的訪問權,還能夠訪問任何虛地址和控制虛擬內存硬件。這種模式對應80×86的ring0層,操作系統的核心部分,包括設備驅動程序都運行在該模式。
②用戶模式
這個模式中,硬件防止特權指令的執行,並對內存和I/O空間的訪問操作進行檢查。這就允許WindowsNT4.0限制任務對各種I/O操作的訪問,並捕捉違反系統完整性的任何行為。在用戶模式中,運行的代碼如果不通過操作系統中的某種門機制,就不能進入內核模式。在80×86處理器上,這個模式對應於 ring3層,操作系統的用戶接口部分以及所有的用戶應用程序都運行在該級別。
windows的用戶棧和內核棧
1、簡介
普通的一個Win32線程有兩個棧:一個是用戶棧,另一個是內核棧;而如果是內核中創建的系統工作線程,則只有內核棧。只要代碼在內核中運行,線程就一定是使用其內核棧的。棧的主要作用是維護函數調用幀,以及為局部變量提供空間。
在Windows里,一個線程的用戶空間的信息都記錄在了TEB中,而TEB中又有一個域叫做NtTib,這里面就存放着有關用戶站的信息。由於TEB結構過於復雜,這里不列舉。
一些需要注意的地方
一個線程用戶棧可以指定其大小,默認是1MB,通過編譯指令/stack可改設其他值。
一個線程普通內核棧的大小是固定的,由系統根據CPU架構而定,x86系統上為12KB,x64系統上為24KB,安騰系統上為32KB。對於GUI線程,普通內核棧空間可能不夠,所以系統又定義了“大內核棧”概念,可以在需要的時候增長棧空間。只有GUI線程才能使用大內核棧,這 也是系統規定的。
Windows將GDI和USER模塊,即“窗口與圖形模塊”的實現移到了內核中,稱為Windows子系統內核服務,並形成一個win32k.sys內核文件。而用戶層僅留調用接口,由User32.dll和GDI32.dll兩個文件暴露出來。判斷一個線程是不是GUI線程的依據,竟非常的簡單:線程初建時,都是普通線程,第一次調用Windows子系統內核服務(只要用戶程序調用了User32.dll和GDI32.dll中的函數,並導致相關內核服務在內核中被執行),系統即立刻將之轉變為GUI線程,並從而切換到“大內核棧”;倘若至線程結束,並未有任何一個子系統內核服務被調用,那么它一直都是普通線程,一直使用普通內核棧。
用戶模式切換到內核模式的情況

