Linux之使用者態和核心態

2021-09-12 06:17:07 字數 3258 閱讀 6551

如上圖所示,從巨集觀上來看,linux作業系統的體系架構分為使用者態和核心態(或者使用者空間和核心)。核心從本質上看是一種軟體——控制計算機的硬體資源,並提供上層應用程式執行的環境。使用者態即上層應用程式的活動空間,應用程式的執行必須依託於核心提供的資源,包括cpu資源、儲存資源、i/o資源等。為了使上層應用能夠訪問到這些資源,核心必須為上層應用提供訪問的介面:即系統呼叫。

系統呼叫是作業系統的最小功能單位,這些系統呼叫根據不同的應用場景可以進行擴充套件和裁剪,現在各種版本的unix實現都提供了不同數量的系統呼叫,如linux的不同版本提供了240-260個系統呼叫,freebsd大約提供了320個(reference:unix環境高階程式設計)。我們可以把系統呼叫看成是一種不能再化簡的操作(類似於原子操作,但是不同概念),有人把它比作乙個漢字的乙個「筆畫」,而乙個「漢字」就代表乙個上層應用,我覺得這個比喻非常貼切。因此,有時候如果要實現乙個完整的漢字(給某個變數分配記憶體空間),就必須呼叫很多的系統呼叫。如果從實現者(程式設計師)的角度來看,這勢必會加重程式設計師的負擔,良好的程式設計方法是:重視上層的業務邏輯操作,而盡可能避免底層複雜的實現細節。庫函式正是為了將程式設計師從複雜的細節中解脫出來而提出的一種有效方法。它實現對系統呼叫的封裝,將簡單的業務邏輯介面呈現給使用者,方便使用者呼叫,從這個角度上看,庫函式就像是組成漢字的「偏旁」。這樣的一種組成方式極大增強了程式設計的靈活性,對於簡單的操作,我們可以直接呼叫系統呼叫來訪問資源,如「人」,對於複雜操作,我們借助於庫函式來實現,如「仁」。顯然,這樣的庫函式依據不同的標準也可以有不同的實現版本,如iso c 標準庫,posix標準庫等。

shell是乙個特殊的應用程式,俗稱命令列,本質上是乙個命令直譯器,它下通系統呼叫,上通各種應用,通常充當著一種「膠水」的角色,來連線各個小功能程式,讓不同程式能夠以乙個清晰的介面協同工作,從而增強各個程式的功能。同時,shell是可程式設計的,它可以執行符合shell語法的文字,這樣的文字稱為shell指令碼,通常短短的幾行shell指令碼就可以實現乙個非常大的功能,原因就是這些shell語句通常都對系統呼叫做了一層封裝。為了方便使用者和系統互動,一般,乙個shell對應乙個終端,終端是乙個硬體裝置,呈現給使用者的是乙個圖形化視窗。我們可以通過這個視窗輸入或者輸出文字。這個文字直接傳遞給shell進行分析解釋,然後執行。

總結一下,使用者態的應用程式可以通過三種方式來訪問核心態的資源:

1)系統呼叫

2)庫函式

3)shell指令碼

有了使用者空間和核心空間,整個linux內部結構可以分為三部分,從最底層到最上層依次是:硬體-->核心空間-->使用者空間。如下圖所示:

需要注意的細節問題:

(1) 核心空間中存放的是核心**和資料,而程序的使用者空間中存放的是使用者程式的**和資料。不管是核心空間還是使用者空間,它們都處於虛擬空間中。 

(2) linux使用兩級保護機制:0級供核心使用,3級供使用者程式使用。

核心態與使用者態:

(1)當乙個任務(程序)執行系統呼叫而陷入核心**中執行時,稱程序處於核心執行態(核心態)。此時處理器處於特權級最高的(0級)核心**中執行。當程序處於核心態時,執行的核心**會使用當前程序的核心棧。每個程序都有自己的核心棧。

(2)當程序在執行使用者自己的**時,則稱其處於使用者執行態(使用者態)。此時處理器在特權級最低的(3級)使用者**中執行。當正在執行使用者程式而突然被中斷程式中斷時,此時使用者程式也可以象徵性地稱為處於程序的核心態。因為中斷處理程式將使用當前程序的核心棧。

二、使用者態和核心態的切換

因為作業系統的資源是有限的,如果訪問資源的操作過多,必然會消耗過多的資源,而且如果不對這些操作加以區分,很可能造成資源訪問的衝突。所以,為了減少有限資源的訪問和使用衝突,unix/linux的設計哲學之一就是:對不同的操作賦予不同的執行等級,就是所謂特權的概念。簡單說就是有多大能力做多大的事,與系統相關的一些特別關鍵的操作必須由最高特權的程式來完成。intel的x86架構的cpu提供了0到3四個特權級,數字越小,特權越高,linux作業系統中主要採用了0和3兩個特權級,分別對應的就是核心態和使用者態。執行於使用者態的程序可以執行的操作和訪問的資源都會受到極大的限制,而執行在核心態的程序則可以執行任何操作並且在資源的使用上沒有限制。很多程式開始時執行於使用者態,但在執行的過程中,一些操作需要在核心許可權下才能執行,這就涉及到乙個從使用者態切換到核心態的過程比如c函式庫中的記憶體分配函式malloc(),它具體是使用sbrk()系統呼叫來分配記憶體,當malloc呼叫sbrk()的時候就涉及一次從使用者態到核心態的切換,類似的函式還有printf(),呼叫的是wirte()系統呼叫來輸出字串,等等。

到底在什麼情況下會發生從使用者態到核心態的切換,一般存在以下三種情況:

1)當然就是系統呼叫:原因如上的分析。

2)異常事件: 當cpu正在執行執行在使用者態的程式時,突然發生某些預先不可知的異常事件,這個時候就會觸發從當前使用者態執行的程序轉向核心態執行相關的異常事件,典型的如缺頁異常。

3)外圍裝置的中斷:當外圍裝置完成使用者的請求操作後,會向cpu發出中斷訊號,此時,cpu就會暫停執行下一條即將要執行的指令,轉而去執行中斷訊號對應的處理程式,如果先前執行的指令是在使用者態下,則自然就發生從使用者態到核心態的轉換。

注意:系統呼叫的本質其實也是中斷,相對於外圍裝置的硬中斷,這種中斷稱為軟中斷,這是作業系統為使用者特別開放的一種中斷,如linux int 80h中斷。所以,從觸發方式和效果上來看,這三種切換方式是完全一樣的,都相當於是執行了乙個中斷響應的過程。但是從觸發的物件來看,系統呼叫是程序主動請求切換的,而異常和硬中斷則是被動的。

Linux探秘之使用者態與核心態

一 unix linux的體系架構 如上圖所示,從巨集觀上來看,linux作業系統的體系架構分為使用者態和核心態 或者使用者空間和核心 核心從本質上看是一種軟體 控制計算機的硬體資源,並提供上層應用程式執行的環境。使用者態即上層應用程式的活動空間,應用程式的執行必須依託於核心提供的資源,包括cpu資...

Linux探秘之使用者態與核心態

unix linux的體系架構 如下圖所示,從巨集觀上來看,linux 作業系統的體系架構分為使用者態和核心態 或者使用者空間和核心 核心從本質上看是一種軟體 控制計算機的硬體資源,並提供上層應用程式執行的環境。使用者態即上層應用程式的活動空間,應用程式的執行必須依託於核心提供的資源,包括 cpu ...

Linux探秘之使用者態與核心態

一 unix linux的體系架構 如上圖所示,從巨集觀上來看,linux作業系統的體系架構分為使用者態和核心態 或者使用者空間和核心 核心從本質上看是一種軟體 控制計算機的硬體資源,並提供上層應用程式執行的環境。使用者態即上層應用程式的活動空間,應用程式的執行必須依託於核心提供的資源,包括cpu資...