最近在學習Linux,提到了內核空間與用戶空間還有上下文切換,個人很有興趣但是這幾個概念太過抽象很難理解,所以找了一些資料整理一下談談自己的理解。個人淺見不涉及太多底層原理,大佬見笑。
- 內核空間與用戶空間
首先看一下我從網上找到的關于內核空間和用戶空間的解釋(來源:https://blog.csdn.net/xiaoaid01/article/details/51659037):
現在操作系統都是采用虛擬存儲器,那么對32位操作系統而言,它的尋址空間(虛擬存儲空間)為4G(2的32次方)。操心系統的核心是內核,獨立于普通的應用程序,可以訪問受保護的內存空間,也有訪問底層硬件設備的所有權限。為了保證用戶進程不能直接操作內核,保證內核的安全,操心系統將虛擬空間劃分為兩部分,一部分為內核空間,一部分為用戶空間。針對linux操作系統而言,將最高的1G字節(從虛擬地址0xC0000000到0xFFFFFFFF),供內核使用,稱為內核空間,而將較低的3G字節(從虛擬地址0x00000000到0xBFFFFFFF),供各個進程使用,稱為用戶空間。每個進程可以通過系統調用進入內核,因此,Linux內核由系統內的所有進程共享。于是,從具體進程的角度來看,每個進程可以擁有4G字節的虛擬空間??臻g分配如下圖:
有些看不太懂哈,不過我們可以簡化提煉一下。簡單來說,這是操作系統的一種安全機制。內核是操作系統的核心,擁有整個操作系統最高的權限,可以訪問所有的硬件。(或者可以理解為內核有控制和分配所有硬件資源的權限)但是,對于普通應用程序來說,這是不必要的,也是不安全的。所以,為了保證內核的安全以及對硬件權限的控制,系統將普通用戶和內核進行隔離劃分出獨立的運行空間,也即是用戶空間和內核空間。如此可以把Linux系統的機構抽象為硬件>內核空間>用戶空間。如下圖:
舉個例子,你(用戶)有一家工廠,但是你并不知道怎么操作工廠里的設備進行生產(計算機運行基于二進制,并不能被直接操作),所以你需要人來進行管理(內核)以及生產(應用程序),其中管理擁有著最大的權力可以控制所有的設備(硬件),出于安全考慮管理和工人的工作區域是完全隔離的(也就是內核空間和用戶空間)。
- 系統調用、API、庫、內核態、用戶態
還是以上的例子,工廠和工人都有了,可以開工了。工人A(應用)說他要去倉庫(硬盤)拿一些材料用來加工,但是他并沒有權限,所以,此時A去請求管理員,管理員把A需要的東西拿過來。這其中A的請求就叫做系統調用。后來又來了許多工人,他們的能力雖然不完全相同,但有些工具卻都需要,于是工廠將這些工具提前準備好公用(這就是庫),工人只需要到特定的位置(API)就可以使用這些工具。
由于某些功能在不同的應用程序中會經常使用,所以為了避免浪費,將這些常用的功能事先編寫打包起來并且留下訪問的接口之后就是庫,不同的應用在使用這些功能的時候只需要通過事先留下的接口就可以使用這些功能,避免了重復開發浪費資源。這些接口就是API。還是用上面的例子解釋,工人A在完成一件事情的過程中出現了兩種狀態,一種是在自己的獨立空間工作,一種是把必須由內核操作的部分交由內核執行,這兩種狀態分別對應的就是用戶態和內核態。需要注意的是這種狀態是針對進程也就是工人A在進行的事情的描述。
- 進程、線程、上下文
我們都知道現在的操作系統都是多任務操作系統,但實際上對于單核心CPU來說,它在某個具體時間只能同時處理一個任務,而多任務的實現,很重要的就是進程的出現。由于在單線程階段CPU只能處理一個任務經常會導致CPU處于空閑狀態而浪費大量資源。進程出現后讓計算機的性能得到了很大的提升,但是后來人們發現CPU會順序處理進程中的每個任務,當一個進程有多個子任務的時候,順序執行帶來的效率問題就出現了,于是,線程的概念也就出現了。線程把進程的子任務進行分割,每個子任務對應一個線程,這樣讓進程內部的并發成為了可能。
那么進程線程是如何解決CPU同時只能處理一個任務從而解決多任務的問題的呢。這里談談我的理解。
首先,進程的是程序在運行時對應的特定內存空間,每個進程的內存空間相互獨立互不干擾,保存著程序運行時每個時刻的狀態,為進程切換提供可能。其次,CPU的運行相對于其他的硬件是非??斓?,以至于CPU實際上長時間是出于空閑狀態的。然后,在CPU開始執行一個程序的時候,與其相關的資源必須已經就位。(比如你去找人辦事,辦事的時候你得把你辦事用的所有東西都準備好)這里除了CPU之外與程序相關的所有資源構成了程序的運行環境,也就是這個程序的上下文。
把這些串起來我們就可以得到下面的信息:我們之前提到CPU同時只能處理一個任務,那當有多個任務同時需要處理怎么辦呢?輪著來,也就是如果有A、B兩個程序同時運行,在CPU這里實際上是這樣的:A→保存A上下文→讀取B上下文→B→保存B上下文→讀取A上下文→A……如此循環直到程序結束,由于CPU運行極快,我們并不能感知到A和B中間短暫的中止狀態,于是在我們看來就像是在同時運行。
那么線程是什么呢,再舉個例子,比如程序A在運行的時候有三個子任務A1、A2、A3由于CPU的特性這三個任務會被順序執行,也就是如果在執行A1的時候我們需要A3的結果單線程的情況下意味著我們只能等待A1、A2、之行結束。這顯然不符合我們的要求,于是線程的概念就出現了,線程把每個進程的子任務獨立出來單個處理,當CPU在處理程序A的時候CPU的運行時間被分成更細小的片段執行,由于不是等待A1執行完在執行A2而是A1→A2→A3→A1→A2→A3……直到執行結束。如下圖:
再加一句,CPU在工作的時候是按照時間片段進行的,靠這些分割的時間片段來回切換實現了多任務。所以也有的人會說線程和進程描述的是CPU時間段。
(線程把進程的CPU時間繼續分割來解決進程的并發問題)
參考:
https://blog.csdn.net/luoweifu/article/details/46595285
https://blog.csdn.net/whl_program/article/details/70217354
https://blog.csdn.net/xiaoaid01/article/details/51659037
https://www.zhihu.com/question/25532384
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/93744
不錯,很有理論功底。