我想準確理解什麼是使用者空間?我問的每個人都說:「任何不是內核的東西」。但對我來說這不是有形的。當我讀到核心可以在用戶空間或類似的東西上運行該驅動程式時;我無法想像會發生什麼事!因此,如果有人在這方面糾正我,我將不勝感激。
答案1
在一個概念層面上,核心是在「更特權」的硬體保護層級上運行的所有東西。這就像x86 處理器上的環0、ARM 上的系統模式、MIPS 上的核心模式、68xxx 上的管理程式模式等。中斷(磁碟機、網路中斷)卡、硬體定時器)。
在同一概念層級上,「使用者空間」是以最低特權模式運作的(x86 CPU 上的環 3、ARM 或 MIPS 上的使用者模式等)。使用者態利用核心平滑微小硬體差異的方式,為所有程式提供相同的 API。例如,某些無線卡可能比其他無線卡具有額外的控制暫存器,或包含更多或更少的用於傳入資料包的板載緩衝區。驅動程式程式碼考慮了這些差異(有時透過忽略高級或不尋常的功能),並向所有程式提供相同的套接字 API。
某些處理器(例如 x86、VAX、Alpha AXP)具有兩種以上的模式,但通用 Unix 架構並未使用中間模式。
您看到的在 Unix、Linux 或 *BSD 中執行的程式和進程都是使用者空間。由於進程是可搶佔的,因此您實際上永遠不會看到核心運行,您只會看到副作用,例如係統read()
呼叫返回或訊號處理函數運行。
為了回答您的特定問題,在 Unix、Linux、*BSD 中,「驅動程式」通常是一些小型軟體,用於處理某些硬體的特定特性:網路卡、磁碟機、顯示卡。驅動程式軟體幾乎總是需要在 Ring 0/管理程式模式/核心空間中運行,以便能夠存取硬體中斷或硬體的映射記憶體等。驅動程式負責特定的硬體功能,並使該硬體符合內核程式碼關於硬體應如何運作的標準化或常規視圖。因此,在用戶態運行驅動程式需要核心向用戶態程式顯示映射記憶體或裝置暫存器或中斷或其他特殊功能等內容。這可能很棘手,因為設備可能需要的特殊功能不容易適應提供給使用者程式的常見 Unix 風格 API。此外,調度也是一個問題,因為使用者態程式通常不會快速回應中斷。
答案2
大多數現代 CPU 都有一個核心或主管模式,以及受限的使用者模式。這是CPU的硬體特性。 「Userland」是在使用者模式下執行的程式碼的另一個名稱。
這些模式之間的一大區別在於大多數現代 CPU 的 MMU 在這些模式下的工作方式。
MMU 允許核心重新排列 RAM 區塊(或頁面),以便它們看起來以與 RAM 中物理順序不同的順序進行編碼,並且還會導致使用者模式程式碼陷阱或者 ”過錯如果造訪某些頁面,則傳回核心模式。
因此,MMU 允許核心模式程式碼執行各種很酷的事情,例如:
- 「安排」或「映射」記憶體到使用者模式代碼,這樣這些代碼就認為它具有連續的 RAM。
- 實現動態記憶體管理方案,進程在嘗試使用記憶體之前需要請求記憶體。
- 如果使用者進程使用了不應該使用的內存,則停止使用者進程。
- 如果可用記憶體不足,則將最少使用的頁面交換到磁碟,並在進程嘗試存取它們時將其交換回來。
您可以看到,MMU 與核心/使用者模式一起是多任務作業系統的基石,使用這些工具可以建立一個可以處理更高層級事物(例如進程概念)的系統。核心為每個進程維護頁表,並在切換到使用者模式之前對 MMU 進行重新編程,並將控制權交給進程的時間片。進程取得記憶體之類的事情malloc
會導致核心修改 MMU 頁表。
再說一次,用戶模式不能對頁表做任何事情(並且不需要知道它們存在),如果它需要內存,它需要稱呼內核,這會導致從用戶模式切換到內核模式。 CPU 提供了一種簡單的機制,稱為軟體中斷去做這個,Linux 核心還有其他更快的方法。
由於使用者模式中存在這種保護,如果程式執行諸如崩潰或失控並覆蓋自身之類的操作,核心可以停止該進程。在核心模式下,這種保護不存在,因此核心將停止工作,從而你的整個系統也將停止工作。當在內核模式下發生此類不可恢復的錯誤時,稱為內核恐慌。看什麼是「內核恐慌」?了解詳情。
核心可以在用戶態上運行該驅動程式
CPU 的核心或管理模式也阻止使用者模式直接存取 I/O 設備,其想法是它必須呼叫核心來做到這一點。在 Linux 中,直接與裝置對話的程式碼(它們在內核模式下運行)是裝置驅動程式(一種核心模組,您可以使用lsmod
、insmod
、modprobe
和rmmod
) 等命令來操作它們。
如果您的裝置驅動程式(在最簡單的設定下以核心模式運行)有一個錯誤,並且做了一些令人討厭的事情,例如覆蓋RAM 中的隨機內容(並且由於它處於核心模式,因此它可以不受限制地存取所有RAM 並且可以覆蓋),會發生什麼情況核心本身)。如果我們能讓裝置驅動程式在用戶模式下運行,這樣它就不能對核心本身或其他進程做任何事情,那就太好了。
不幸的是,從用戶模式切換到核心模式(稱為上下文切換)很慢,因為基本上每個行程或核心本身都必須切換 CPU 的整個狀態。因此,我們有兩件事存在分歧:安全性或速度,因此這是一個爭論點和設計點。
嘗試在用戶模式下做盡可能多的事情的核心被稱為微內核,而Linux則相反,稱為整體式的。 Linux 確實存在使用者模式驅動程式(以 FUSE 為例),甚至還有一個框架這允許它。
答案3
根據 Bruce 所說,提供給核心的所有程式碼都必須可信。如果核心可以透過某種方式執行惡意程式碼,那麼遊戲就結束了。這就是用戶執行程式碼和核心執行程式碼的權限分離發揮作用的地方。用戶運行的程式碼不一定 100% 沒有邪惡。它不直接由內核執行。
用戶態程式只是與核心的公開部分交互,例如 API 和載入的模組。一個例子是iptables
。有幾個核心模組 (.ko) 或「驅動程式」實際上完成 的工作iptables
,它們是網路過濾框架。當您執行命令時,/sbin/iptables
您正在使用使用者層元件,該元件又與載入到核心中的 netfilter 模組進行通訊。這允許分離,以便核心不會無意中執行使用者程式碼。
答案4
在 Unix/Linux 作業系統中,我們的差別在於使用者空間和核心空間。這只是用戶空間和核心所屬位置的同義詞。
你可以這樣理解。您可以與用戶空間中發生的所有事情進行互動。在核心空間中並非如此。守護程式、函式庫和應用程式都屬於使用者空間。所有在作業系統核心之外運行的程式碼都屬於使用者空間(userland)。
核心空間是核心本身運作的地方。這是一個連 root 都無法存取的禁區。但是 root 使用者可以透過核心提供的介面(procfs、sysfs)來操作一些核心參數。
系統記憶體是解釋核心空間和使用者空間之間差異的一個很好的例子。守護進程(在用戶空間中運行)需要一些記憶體才能運行。核心管理所有可用的記憶體。守護程式從核心獲取一些“虛擬記憶體”,守護程式不知道它是實體記憶體還是交換空間還是其他什麼。內核決定進程取得哪種記憶體。因為記憶體管理發生在核心空間。核心空間中發生的其他事情包括進程調度、進程間通訊、記憶體保護和管理、系統呼叫......
用戶態到底是什麼?
因此,使用者態是守護程式在與作業系統資源(I/O、網路、記憶體、CPU 時間)互動時所做(或可以做)的事情。這些資源對核心空間中的進程是隱藏的。
簡短的回答:
這就是飛行員的飛機駕駛艙。