咱們先來看一張Linux
總體架構圖。html
系統調用時操做系統的最小功能單位。根據不一樣的應用場景,不一樣的Linux
發行版本提供的系統調用數量也不盡相同,大體在240-350之間。這些系統調用組成了用戶態跟內核態交互的基本接口,例如:用戶態想要申請一塊20K大小的動態內存,就須要brk系統調用,將數據段指針向下偏移,若是用戶態多處申請20K動態內存,同時又釋放呢?這個內存的管理就變得很是的複雜。程序員
庫函數就是屏蔽這些複雜的底層實現細節,減輕程序員的負擔,從而更加關注上層的邏輯實現。它對系統調用進行封裝,提供簡單的基本接口給用戶,這樣加強了程序的靈活性,固然對於簡單的接口,也能夠直接使用系統調用訪問資源,例如:open()
,write()
,read()
等等。庫函數根據不一樣的標準也有不一樣的版本,例如:glibc
庫,posix
庫等。shell
Shell
顧名思義,就是外殼的意思。就好像把內核包裹起來的外殼。它是一種特殊的應用程序,俗稱命令行。爲了方便用戶和系統交互,通常一個Shell
對應一個終端,呈現給用戶交互窗口。固然Shell
也是編程的,它有標準的shell
語法,符合其語法的文本叫Shell
腳本。不少人都會用Shell
腳本實現一些經常使用的功能,能夠提升工做效率。編程
在CPU
的全部指令中,有一些指令是很是危險的,若是錯用,將致使整個系統崩潰。好比:清內存、設置時鐘等。若是全部的程序都能使用這些指令,那麼你的系統一天死機N回就不足爲奇了。因此,CPU
將指令分爲特權指令和非特權指令,對於那些危險的指令,只容許操做系統及其相關模塊使用,普通的應用程序只能使用那些不會形成災難的指令。Intel
的CPU
將特權級別分爲4個級別:RING0
、RING1
、RING2
、RING3
。安全
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,咱們就稱進程處於內核運行態(或簡稱爲內核態)。此時處理器處於特權級最高的(0級)內核代碼中執行。微信
當正在執行用戶程序而忽然被中斷程序中斷時,此時用戶程序也能夠象徵性地稱爲處於進程的內核態。Linux
使用了Ring3
級別運行用戶態,Ring0
做爲 內核態,沒有使用Ring1
和Ring2
。Ring3
狀態不能訪問Ring0
的地址空間,包括代碼和數據。Linux
進程的4GB
地址空間,3G-4G部分你們是共享的,是內核態的地址空間,這裏存放在整個內核的代碼和全部的內核模塊,以及內核所維護的數據。用戶運行一個程序,該程序所建立的進程開始是運 行在用戶態的,若是要執行文件操做,網絡數據發送等操做,必須經過write
,send
等系統調用,這些系統調用會調用內核中的代碼來完成操做,這時,必 須切換到Ring0
,而後進入3GB-4GB
中的內核地址空間去執行這些代碼完成操做,完成後,切換回Ring3
,回到用戶態。網絡
這樣,用戶態的程序就不能 隨意操做內核地址空間,具備必定的安全保護做用。架構
處理器總處於如下狀態中的一種:函數
一、內核態,運行於進程上下文,內核表明進程運行於內核空間;操作系統
二、內核態,運行於中斷上下文,內核表明硬件運行於內核空間;
三、用戶態,運行於用戶空間。
從用戶態到內核態切換能夠經過三種方式:
**系統調用:**這是用戶態進程主動要求切換到內核態的一種方式,用戶態進程經過系統調用申請使用操做系統提供的服務程序完成工做,好比前例中fork()實際上就是執行了一個建立新進程的系統調用。而系統調用的機制其核心仍是使用了操做系統爲用戶特別開放的一箇中斷來實現,例如Linux的int 80h中斷。
**異常:**當CPU在執行運行在用戶態下的程序時,發生了某些事先不可知的異常,這時會觸發由當前運行進程切換處處理此異常的內核相關程序中,也就轉到了內核態,好比缺頁異常。
**外設中斷:**當外圍設備完成用戶請求的操做後,會向CPU發出相應的中斷信號,這時CPU會暫停執行下一條即將要執行的指令轉而去執行與中斷信號對應的處理程序,若是先前執行的指令是用戶態下的程序,那麼這個轉換的過程天然也就發生了由用戶態到內核態的切換。好比硬盤讀寫操做完成,系統會切換到硬盤讀寫的中斷處理程序中執行後續操做等。
這3種方式是系統在運行時由用戶態轉到內核態的最主要方式,其中系統調用能夠認爲是用戶進程主動發起的,異常和外圍設備中斷則是被動的。
若是你們喜歡個人文章,能夠關注我的訂閱號。歡迎隨時留言、交流。若是想加入微信羣的話一塊兒討論的話,請加管理員簡棧文化-小助手(lastpass4u),他會拉大家進羣。