一、 Unix/Linux的體系架構(gòu) 如上圖所示,,從宏觀上來看,,Linux操作系統(tǒng)的體系架構(gòu)分為用戶態(tài)和內(nèi)核態(tài)(或者用戶空間和內(nèi)核)。內(nèi)核從本質(zhì)上看是一種軟件——控制計(jì)算機(jī)的硬件資源,,并提供上層應(yīng)用程序運(yùn)行的環(huán)境,。用戶態(tài)即上層應(yīng)用程序的活動空間,應(yīng)用程序的執(zhí)行必須依托于內(nèi)核提供的資源,,包括CPU資源,、存儲資源、I/O資源等,。為了使上層應(yīng)用能夠訪問到這些資源,,內(nèi)核必須為上層應(yīng)用提供訪問的接口:即系統(tǒng)調(diào)用。 系統(tǒng)調(diào)用是操作系統(tǒng)的最小功能單位,,這些系統(tǒng)調(diào)用根據(jù)不同的應(yīng)用場景可以進(jìn)行擴(kuò)展和裁剪,,現(xiàn)在各種版本的Unix實(shí)現(xiàn)都提供了不同數(shù)量的系統(tǒng)調(diào)用,如Linux的不同版本提供了240-260個系統(tǒng)調(diào)用,,F(xiàn)reeBSD大約提供了320個(reference:UNIX環(huán)境高級編程),。我們可以把系統(tǒng)調(diào)用看成是一種不能再化簡的操作(類似于原子操作,但是不同概念),,有人把它比作一個漢字的一個“筆畫”,,而一個“漢字”就代表一個上層應(yīng)用,我覺得這個比喻非常貼切,。因此,,有時候如果要實(shí)現(xiàn)一個完整的漢字(給某個變量分配內(nèi)存空間),就必須調(diào)用很多的系統(tǒng)調(diào)用,。如果從實(shí)現(xiàn)者(程序員)的角度來看,,這勢必會加重程序員的負(fù)擔(dān),良好的程序設(shè)計(jì)方法是:重視上層的業(yè)務(wù)邏輯操作,,而盡可能避免底層復(fù)雜的實(shí)現(xiàn)細(xì)節(jié),。庫函數(shù)正是為了將程序員從復(fù)雜的細(xì)節(jié)中解脫出來而提出的一種有效方法,。它實(shí)現(xiàn)對系統(tǒng)調(diào)用的封裝,,將簡單的業(yè)務(wù)邏輯接口呈現(xiàn)給用戶,,方便用戶調(diào)用,從這個角度上看,,庫函數(shù)就像是組成漢字的“偏旁”,。這樣的一種組成方式極大增強(qiáng)了程序設(shè)計(jì)的靈活性,對于簡單的操作,,我們可以直接調(diào)用系統(tǒng)調(diào)用來訪問資源,,如“人”,對于復(fù)雜操作,,我們借助于庫函數(shù)來實(shí)現(xiàn),,如“仁”。顯然,,這樣的庫函數(shù)依據(jù)不同的標(biāo)準(zhǔn)也可以有不同的實(shí)現(xiàn)版本,,如ISO C 標(biāo)準(zhǔn)庫,POSIX標(biāo)準(zhǔn)庫等,。 Shell是一個特殊的應(yīng)用程序,,俗稱命令行,本質(zhì)上是一個命令解釋器,,它下通系統(tǒng)調(diào)用,,上通各種應(yīng)用,通常充當(dāng)著一種“膠水”的角色,,來連接各個小功能程序,,讓不同程序能夠以一個清晰的接口協(xié)同工作,從而增強(qiáng)各個程序的功能,。同時,,Shell是可編程的,它可以執(zhí)行符合Shell語法的文本,,這樣的文本稱為Shell腳本,,通常短短的幾行Shell腳本就可以實(shí)現(xiàn)一個非常大的功能,原因就是這些Shell語句通常都對系統(tǒng)調(diào)用做了一層封裝,。為了方便用戶和系統(tǒng)交互,,一般,一個Shell對應(yīng)一個終端,,終端是一個硬件設(shè)備,,呈現(xiàn)給用戶的是一個圖形化窗口。我們可以通過這個窗口輸入或者輸出文本,。這個文本直接傳遞給shell進(jìn)行分析解釋,,然后執(zhí)行。 總結(jié)一下,用戶態(tài)的應(yīng)用程序可以通過三種方式來訪問內(nèi)核態(tài)的資源: 1)系統(tǒng)調(diào)用 2)庫函數(shù) 3)Shell腳本 下圖是對上圖的一個細(xì)分結(jié)構(gòu),,從這個圖上可以更進(jìn)一步對內(nèi)核所做的事有一個“全景式”的印象,。主要表現(xiàn)為:向下控制硬件資源,向內(nèi)管理操作系統(tǒng)資源:包括進(jìn)程的調(diào)度和管理,、內(nèi)存的管理,、文件系統(tǒng)的管理、設(shè)備驅(qū)動程序的管理以及網(wǎng)絡(luò)資源的管理,,向上則向應(yīng)用程序提供系統(tǒng)調(diào)用的接口,。從整體上來看,整個操作系統(tǒng)分為兩層:用戶態(tài)和內(nèi)核態(tài),,這種分層的架構(gòu)極大地提高了資源管理的可擴(kuò)展性和靈活性,,而且方便用戶對資源的調(diào)用和集中式的管理,帶來一定的安全性,。 二,、用戶態(tài)和內(nèi)核態(tài)的切換 因?yàn)椴僮飨到y(tǒng)的資源是有限的,如果訪問資源的操作過多,,必然會消耗過多的資源,,而且如果不對這些操作加以區(qū)分,很可能造成資源訪問的沖突,。所以,,為了減少有限資源的訪問和使用沖突,Unix/Linux的設(shè)計(jì)哲學(xué)之一就是:對不同的操作賦予不同的執(zhí)行等級,,就是所謂特權(quán)的概念,。簡單說就是有多大能力做多大的事,與系統(tǒng)相關(guān)的一些特別關(guān)鍵的操作必須由最高特權(quán)的程序來完成,。Intel的X86架構(gòu)的CPU提供了0到3四個特權(quán)級,,數(shù)字越小,特權(quán)越高,,Linux操作系統(tǒng)中主要采用了0和3兩個特權(quán)級,,分別對應(yīng)的就是內(nèi)核態(tài)和用戶態(tài)。運(yùn)行于用戶態(tài)的進(jìn)程可以執(zhí)行的操作和訪問的資源都會受到極大的限制,,而運(yùn)行在內(nèi)核態(tài)的進(jìn)程則可以執(zhí)行任何操作并且在資源的使用上沒有限制,。很多程序開始時運(yùn)行于用戶態(tài),但在執(zhí)行的過程中,,一些操作需要在內(nèi)核權(quán)限下才能執(zhí)行,,這就涉及到一個從用戶態(tài)切換到內(nèi)核態(tài)的過程。比如C函數(shù)庫中的內(nèi)存分配函數(shù)malloc(),,它具體是使用sbrk()系統(tǒng)調(diào)用來分配內(nèi)存,,當(dāng)malloc調(diào)用sbrk()的時候就涉及一次從用戶態(tài)到內(nèi)核態(tài)的切換,,類似的函數(shù)還有printf(),調(diào)用的是wirte()系統(tǒng)調(diào)用來輸出字符串,,等等,。 到底在什么情況下會發(fā)生從用戶態(tài)到內(nèi)核態(tài)的切換,一般存在以下三種情況: 1)當(dāng)然就是系統(tǒng)調(diào)用:原因如上的分析,。 2)異常事件: 當(dāng)CPU正在執(zhí)行運(yùn)行在用戶態(tài)的程序時,突然發(fā)生某些預(yù)先不可知的異常事件,,這個時候就會觸發(fā)從當(dāng)前用戶態(tài)執(zhí)行的進(jìn)程轉(zhuǎn)向內(nèi)核態(tài)執(zhí)行相關(guān)的異常事件,,典型的如缺頁異常。 3)外圍設(shè)備的中斷:當(dāng)外圍設(shè)備完成用戶的請求操作后,,會像CPU發(fā)出中斷信號,,此時,CPU就會暫停執(zhí)行下一條即將要執(zhí)行的指令,,轉(zhuǎn)而去執(zhí)行中斷信號對應(yīng)的處理程序,,如果先前執(zhí)行的指令是在用戶態(tài)下,則自然就發(fā)生從用戶態(tài)到內(nèi)核態(tài)的轉(zhuǎn)換,。 注意:系統(tǒng)調(diào)用的本質(zhì)其實(shí)也是中斷,,相對于外圍設(shè)備的硬中斷,這種中斷稱為軟中斷,,這是操作系統(tǒng)為用戶特別開放的一種中斷,,如Linux int 80h中斷。所以,,從觸發(fā)方式和效果上來看,,這三種切換方式是完全一樣的,都相當(dāng)于是執(zhí)行了一個中斷響應(yīng)的過程,。但是從觸發(fā)的對象來看,,系統(tǒng)調(diào)用是進(jìn)程主動請求切換的,而異常和硬中斷則是被動的,。 三,、總結(jié) 本文僅是從宏觀的角度去理解Linux用戶態(tài)和內(nèi)核態(tài)的設(shè)計(jì),并沒有去深究它們的具體實(shí)現(xiàn)方式,。從實(shí)現(xiàn)上來看,,必須要考慮到的一點(diǎn)我想就是性能問題,因?yàn)橛脩魬B(tài)和內(nèi)核態(tài)之間的切換也會消耗大量資源,。關(guān)于實(shí)現(xiàn)的細(xì)節(jié),,目前學(xué)藝不精不敢亂說,等日后補(bǔ)上,。但知道了這一點(diǎn),,我相信對很多問題也就很容易理解了,,比如說基于緩沖區(qū)的IO和無緩沖的IO,用戶進(jìn)程和內(nèi)核進(jìn)程之間的切換,,IO復(fù)用中的讀寫內(nèi)核事件表,,等等,這些知識之后會一一補(bǔ)上,。 |
|