在Linux技術討論中經常會用戶態內核態術語脫口而出,可你們想過嗎?用戶態和內核態代表是什麼?本片文章,就來談一談這個話題。

我們先來看一張Linux整體架構圖。

從圖上我們可以看出來通過系統調用將Linux整個體系分為用戶態和內核態(或者說內核空間和用戶空間)。那內核態到底是什麼呢?其實從本質上說就是我們所說的內核,它是一種特殊的軟體程序,特殊在哪兒呢?控制計算機的硬體資源,例如協調CPU資源,分配內存資源,並且提供穩定的環境供應用程序運行

用戶態就是提供應用程序運行的空間,為了使應用程序訪問到內核管理的資源例如CPU,內存,I/O。內核必須提供一組通用的訪問介面,這些介面就叫系統調用。

系統調用

系統調用時操作系統的最小功能單位。根據不同的應用場景,不同的Linux發行版本提供的系統調用數量也不盡相同,大致在240-350之間。這些系統調用組成了用戶態跟內核態交互的基本介面,例如:用戶態想要申請一塊20K大小的動態內存,就需要brk系統調用,將數據段指針向下偏移,如果用戶態多處申請20K動態內存,同時又釋放呢?這個內存的管理就變得非常的複雜。

庫函數

庫函數就是屏蔽這些複雜的底層實現細節,減輕程序員的負擔,從而更加關註上層的邏輯實現。它對系統調用進行封裝,提供簡單的基本介面給用戶,這樣增強了程序的靈活性,當然對於簡單的介面,也可以直接使用系統調用訪問資源,例如:open(),write(),read()等等。庫函數根據不同的標準也有不同的版本,例如:glibc庫,posix庫等。

shell

shell顧名思義,就是外殼的意思。就好像把內核包裹起來的外殼。它是一種特殊的應用程序,俗稱命令行。為了方便用戶和系統交互,一般一個shell對應一個終端,呈現給用戶交互窗口。當然shell也是編程的,它有標準的shell語法,符合其語法的文本叫shell腳本。很多人都會用shell腳本實現一些常用的功能,可以提高工作效率。

我們再來看一個更加細化的Linux體系架構圖。我們可以總結下:內核控制並且管理硬體資源,包括進程的調度和管理、內存管理、文件系統管理、設備驅動管理、網路管理等等。並且提供應用程序統一的系統調用介面。這種分層的架構,極大的提升了系統的穩定性和擴展性,兼容性。

用戶態到內核態怎樣切換?

往往我們的系統的資源是固定的,例如內存2G,CPU固定,磁碟2TB,網路介面固定。所以就需要操作系統對資源進行有效的利用。假設某個應用程序過分的訪問這些資源,就會導致整個系統的資源被佔用,如果不對這種行為進行限制和區分,就會導致資源訪問的衝突。所以,Linux的設計的初衷:給不同的操作給與不同的「許可權」。Linux操作系統就將許可權等級分為了2個等級,分別就是內核態和用戶態。

各位有沒有發現,前面講了這麼多內核態和用戶態什麼不同,其實用一句話就能概括:它們許可權不同。用戶態的進程能夠訪問的資源受到了極大的控制,而運行在內核態的進程可以「為所欲為」。一個進程可以運行在用戶態也可以運行在內核態,那它們之間肯定存在用戶態和內核態切換的過程。打一個比方:C庫介面malloc申請動態內存,malloc的實現內部最終還是會調用brk()或者mmap()系統調用來分配內存。

那為問題又來了,從用戶態到內核態到底怎麼進入?只能通過系統調用嗎?還有其他方式嗎?

從用戶態到內核態切換可以通過三種方式:

  1. 系統調用,這個上面已經講解過了,在我公眾號之前的文章也有講解過。其實系統調用本身就是中斷,但是軟體中斷,跟硬中斷不同。
  2. 異常:如果當前進程運行在用戶態,如果這個時候發生了異常事件,就會觸發切換。例如:缺頁異常。
  3. 外設中斷:當外設完成用戶的請求時,會向CPU發送中斷信號。

總結

本片文章,沒有非常深入的Linux內核實現,只是從宏觀的角度闡述了下。看完上面的文章,也能得出一點結論就是:系統調用真的開銷蠻大的。涉及到上下文的切換。在上篇文章中【Linux的直接I/O原理】中有講述到這些,Linux內核真的是複雜的工程,更多技術細節,需要點滴積累。

覺得不錯,記得關注、點贊、轉發、「在看」

推薦閱讀:

相關文章