內(nèi)核態(tài)與用戶態(tài)
內(nèi)核態(tài)與用戶態(tài)是操作系統(tǒng)的兩種運(yùn)行級(jí)別,intel cpu提供Ring0-Ring3三種級(jí)別的運(yùn)行模式。Ring0級(jí)別最高,Ring3最低。其中特權(quán)級(jí)0(Ring0)是留給操作系統(tǒng)代碼,設(shè)備驅(qū)動(dòng)程序代碼使用的,它們工作于系統(tǒng)核心態(tài);而特權(quán)極3(Ring3)則給普通的用戶程序使用,它們工作在用戶態(tài)。運(yùn)行于處理器核心態(tài)的代碼不受任何的限制,可以自由地訪問(wèn)任何有效地址,進(jìn)行直接端口訪問(wèn)。而運(yùn)行于用戶態(tài)的代碼則要受到處理器的諸多檢查,它們只能訪問(wèn)映射其地址空間的頁(yè)表項(xiàng)中規(guī)定的在用戶態(tài)下可訪問(wèn)頁(yè)面的虛擬地址,且只能對(duì)任務(wù)狀態(tài)段(TSS)中I/O許可位圖(I/O Permission Bitmap)中規(guī)定的可訪問(wèn)端口進(jìn)行直接訪問(wèn)(此時(shí)處理器狀態(tài)和控制標(biāo)志寄存器EFLAGS中的IOPL通常為0,指明當(dāng)前可以進(jìn)行直接I/O的最低特權(quán)級(jí)別是Ring0)。以上的討論只限于保護(hù)模式操作系統(tǒng),象DOS這種模式操作系統(tǒng)則沒(méi)有這些概念,其中的所有代碼都可被看作運(yùn)行在核心態(tài)。
當(dāng)一個(gè)任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時(shí),我們就稱進(jìn)程處于內(nèi)核運(yùn)行態(tài)(或簡(jiǎn)稱為內(nèi)核態(tài))。此時(shí)處理器處于特權(quán)級(jí)最高的(0級(jí)) 內(nèi)核代碼中執(zhí)行。當(dāng)進(jìn)程處于內(nèi)核態(tài)時(shí),執(zhí)行的內(nèi)核代碼會(huì)使用當(dāng)前進(jìn)程的內(nèi)核棧。每個(gè)進(jìn)程都有自己的內(nèi)核棧。當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼時(shí),則稱其處于用戶運(yùn)行態(tài)(用戶態(tài))。即此時(shí)處理器在特權(quán)級(jí)最低的(3級(jí))用戶代碼中運(yùn)行。
在內(nèi)核態(tài)下CPU可執(zhí)行任何指令,在用戶態(tài)下CPU只能執(zhí)行非特權(quán)指令。當(dāng)CPU處于內(nèi)核態(tài),可以隨意進(jìn)入用戶態(tài);而當(dāng)CPU處于用戶態(tài)時(shí),用戶從用戶態(tài)切換到內(nèi)核態(tài)只有在系統(tǒng)調(diào)用和中斷兩種情況下發(fā)生,一般程序一開(kāi)始都是運(yùn)行于用戶態(tài),當(dāng)程序需要使用系統(tǒng)資源時(shí),就必須通過(guò)調(diào)用軟中斷進(jìn)入內(nèi)核態(tài)。
Linux使用了Ring3級(jí)別運(yùn)行用戶態(tài),Ring0作為內(nèi)核態(tài),沒(méi)有使用Ring1和Ring2。Ring3狀態(tài)不能訪問(wèn)Ring0的地址空間,包括代碼和數(shù)據(jù)。Linux進(jìn)程的4GB地址空間,3G-4G部分大家是共享的,是內(nèi)核態(tài)的地址空間,這里存放在整個(gè)內(nèi)核的代碼和所有的內(nèi)核模塊,以及內(nèi)核所維護(hù)的數(shù)據(jù)。用戶運(yùn)行一個(gè)程序,該程序所創(chuàng)建的進(jìn)程開(kāi)始是運(yùn)行在用戶態(tài)的,如果要執(zhí)行文件操作,網(wǎng)絡(luò)數(shù)據(jù)發(fā)送等操作,必須通過(guò) write,send等系統(tǒng)調(diào)用,這些系統(tǒng)調(diào)用會(huì)調(diào)用內(nèi)核中的代碼來(lái)完成操作,這時(shí),必須切換到Ring0,然后進(jìn)入3GB-4GB中的內(nèi)核地址空間去執(zhí)行這些代碼完成操作,完成后,切換回Ring3,回到用戶態(tài)。這樣,用戶態(tài)的程序就不能隨意操作內(nèi)核地址空間,具有一定的安全保護(hù)作用。
處理器模式從Ring3向Ring0的切換發(fā)生在控制權(quán)轉(zhuǎn)移時(shí),有以下兩種情況:訪問(wèn)調(diào)用門的長(zhǎng)轉(zhuǎn)移指令CALL,訪問(wèn)中斷門或陷阱門的INT指令。具體的轉(zhuǎn)移細(xì)節(jié)由于涉及復(fù)雜的保護(hù)檢查和堆棧切換,不再贅述,請(qǐng)參閱相關(guān)資料?,F(xiàn)代的操作系統(tǒng)通常使用中斷門來(lái)提供系統(tǒng)服務(wù),通過(guò)執(zhí)行一條陷入指令來(lái)完成模式切換,在INTEL X86上這條指令是INT,如在WIN9X下是INT30(保護(hù)模式回調(diào)),在LINUX下是INT80,在WINNT/2000下是INT2E。用戶模式的服務(wù)程序(如系統(tǒng)DLL)通過(guò)執(zhí)行一個(gè)INTXX來(lái)請(qǐng)求系統(tǒng)服務(wù),然后處理器模式將切換到核心態(tài),工作于核心態(tài)的相應(yīng)的系統(tǒng)代碼將服務(wù)于此次請(qǐng)求并將結(jié)果傳給用戶程序。
一,中斷處理過(guò)程
硬件中斷:來(lái)自時(shí)鐘,外設(shè)
可編程中斷:programmed interrupt,執(zhí)行引起軟件中斷的指令。
例外中斷:如頁(yè)面錯(cuò)。
都由系統(tǒng)負(fù)責(zé)處理。當(dāng)發(fā)生一個(gè)中斷時(shí),如果CPU正在比該中斷級(jí)低的處理機(jī)運(yùn)行級(jí)上運(yùn)行,它就在解碼下條指令之前,接受該中斷,并提高處理機(jī)運(yùn)行級(jí)。內(nèi)核處理中斷的操作順序如下:
1,對(duì)于正在進(jìn)行的進(jìn)程,保存其當(dāng)前寄存器上下文,并創(chuàng)建壓入一個(gè)新的上下文層。
2,確定中斷源,識(shí)別中斷類型。如是時(shí)鐘或磁盤的。
3,查找中斷向量。當(dāng)系統(tǒng)接受一個(gè)中斷時(shí),它從機(jī)器中得到一個(gè)數(shù),系統(tǒng)把這個(gè)作為查表的偏移量。這個(gè)表通常成為中斷向量(interrupt vector)。中斷向量的內(nèi)容包括各種中斷源的中斷處理程序的地址,以及中斷處理程序取得參數(shù)的方式。
4,內(nèi)核調(diào)用中斷處理程序。
5,中斷處理程序執(zhí)行那個(gè)返回,恢復(fù)(彈出)前一上下文層。
二,軟中斷
軟中斷通知進(jìn)程發(fā)生了異步事件。
系統(tǒng)有個(gè)進(jìn)程表,每個(gè)進(jìn)程在進(jìn)程表中有有個(gè)進(jìn)程表項(xiàng),每個(gè)進(jìn)程表項(xiàng)有個(gè)軟中斷信號(hào)字段,紀(jì)錄發(fā)向一個(gè)進(jìn)程的所有未處理的軟中斷信號(hào)。
當(dāng)一個(gè)進(jìn)程即將從核心態(tài)返回到用戶態(tài)時(shí),或它要進(jìn)入或離開(kāi)一個(gè)適當(dāng)?shù)牡驼{(diào)度優(yōu)先級(jí)時(shí),內(nèi)核要檢查它是否收到了一個(gè)軟中斷信號(hào)。
內(nèi)核僅當(dāng)一個(gè)進(jìn)程從核心態(tài)返回到用戶態(tài)時(shí)才處理軟中斷信號(hào)。
三,系統(tǒng)調(diào)用
我們?cè)贑程序中調(diào)用系統(tǒng)調(diào)用好像是個(gè)一般的函數(shù)調(diào)用,當(dāng)實(shí)際上調(diào)用系統(tǒng)調(diào)用會(huì)引起用戶態(tài)到核心態(tài)的狀態(tài)變化,這是怎么做到的呢?
原來(lái),C編譯程序采用一個(gè)預(yù)定義的函數(shù)庫(kù)(C之程序庫(kù)),其中的函數(shù)具有系統(tǒng)調(diào)用的名字,從而解決了在用戶程序中請(qǐng)求系統(tǒng)調(diào)用的問(wèn)題。這些庫(kù)函數(shù)一般都執(zhí)行一條指令,該指令將進(jìn)程的運(yùn)行方式變?yōu)楹诵膽B(tài),然后,使內(nèi)核開(kāi)始為系統(tǒng)調(diào)用執(zhí)行代碼。我們稱這個(gè)指令為操作系統(tǒng)陷入(operating system trap)。
系統(tǒng)調(diào)用的接口是一個(gè)中斷處理程序的特例。
在處理操作系統(tǒng)陷入時(shí),
1,內(nèi)核根據(jù)系統(tǒng)調(diào)用號(hào)查系統(tǒng)調(diào)用入口表,找到相應(yīng)的內(nèi)核子程序的地址。
2,內(nèi)核還要確定該系統(tǒng)調(diào)用所要求的參數(shù)個(gè)數(shù)。
3,從用戶地址空間拷貝參數(shù)到U區(qū)(Unix V)。
4,保存當(dāng)前上下文,執(zhí)行系統(tǒng)調(diào)用代碼。
核心態(tài):當(dāng)CPU正在運(yùn)行內(nèi)核代碼時(shí)(內(nèi)核代碼是共享的)。
用戶態(tài):當(dāng)CPU正在運(yùn)行用戶代碼時(shí)。
用戶模式:不可以訪問(wèn)內(nèi)核空間(>=0x80000000)
內(nèi)核模式:可以訪問(wèn)任何有效虛擬地址,包括內(nèi)核空間。一個(gè)線程可以訪問(wèn)其他任何線程地址空間。
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:
http://blog.csdn.net/skywalkzf/archive/2010/01/13/5185442.aspx