用户模式和内核模式
link
首先我們要解釋一個(gè)概念——進(jìn)程(Process)。簡單來說,一個(gè)可執(zhí)行程序就是一個(gè)進(jìn)程,前面我們使用C語言編譯生成的程序,運(yùn)行后就是一個(gè)進(jìn)程。進(jìn)程最顯著的特點(diǎn)就是擁有獨(dú)立的地址空間。嚴(yán)格來說,程序是存儲(chǔ)在磁盤上的一個(gè)文件,是指令和數(shù)據(jù)的集合,是一個(gè)靜態(tài)的概念;進(jìn)程是程序加載到內(nèi)存運(yùn)行后一些列的活動(dòng),是一個(gè)動(dòng)態(tài)的概念。
前面我們?cè)谥v解地址空間時(shí),一直說“程序的地址空間”,這其實(shí)是不嚴(yán)謹(jǐn)?shù)?#xff0c;應(yīng)該說“進(jìn)程的地址空間”。一個(gè)進(jìn)程對(duì)應(yīng)一個(gè)地址空間,而一個(gè)程序可能會(huì)創(chuàng)建多個(gè)進(jìn)程。
內(nèi)核模式和用戶模式
內(nèi)核空間存放的是操作系統(tǒng)內(nèi)核代碼和數(shù)據(jù),是被所有程序共享的,在程序中修改內(nèi)核空間中的數(shù)據(jù)不僅會(huì)影響操作系統(tǒng)本身的穩(wěn)定性,還會(huì)影響其他程序,這是非常危險(xiǎn)的行為,所以操作系統(tǒng)禁止用戶程序直接訪問內(nèi)核空間。要想訪問內(nèi)核空間,必須借助操作系統(tǒng)提供的 API 函數(shù),執(zhí)行內(nèi)核提供的代碼,讓內(nèi)核自己來訪問,這樣才能保證內(nèi)核空間的數(shù)據(jù)不會(huì)被隨意修改,才能保證操作系統(tǒng)本身和其他程序的穩(wěn)定性。
用戶程序調(diào)用系統(tǒng) API 函數(shù)稱為系統(tǒng)調(diào)用(System Call);發(fā)生系統(tǒng)調(diào)用時(shí)會(huì)暫停用戶程序,轉(zhuǎn)而執(zhí)行內(nèi)核代碼(內(nèi)核也是程序),訪問內(nèi)核空間,這稱為內(nèi)核模式(Kernel Mode)。
用戶空間保存的是應(yīng)用程序的代碼和數(shù)據(jù),是程序私有的,其他程序一般無法訪問。當(dāng)執(zhí)行應(yīng)用程序自己的代碼時(shí),稱為用戶模式(User Mode)。
計(jì)算機(jī)會(huì)經(jīng)常在內(nèi)核模式和用戶模式之間切換:
- 當(dāng)運(yùn)行在用戶模式的應(yīng)用程序需要輸入輸出、申請(qǐng)內(nèi)存等比較底層的操作時(shí),就必須調(diào)用操作系統(tǒng)提供的 API 函數(shù),從而進(jìn)入內(nèi)核模式;
- 操作完成后,繼續(xù)執(zhí)行應(yīng)用程序的代碼,就又回到了用戶模式。
總結(jié):用戶模式就是執(zhí)行應(yīng)用程序代碼,訪問用戶空間;內(nèi)核模式就是執(zhí)行內(nèi)核代碼,訪問內(nèi)核空間(當(dāng)然也有權(quán)限訪問用戶空間)。
為什么要區(qū)分兩種模式
我們知道,內(nèi)核最主要的任務(wù)是管理硬件,包括顯示器、鍵盤、鼠標(biāo)、內(nèi)存、硬盤等,并且內(nèi)核也提供了接口(也就是函數(shù)),供上層程序使用。當(dāng)程序要進(jìn)行輸入輸出、分配內(nèi)存、響應(yīng)鼠標(biāo)等與硬件有關(guān)的操作時(shí),必須要使用內(nèi)核提供的接口。但是用戶程序是非常不安全的,內(nèi)核對(duì)用戶程序也是充分不信任的,當(dāng)程序調(diào)用內(nèi)核接口時(shí),內(nèi)核要做各種校驗(yàn),以防止出錯(cuò)。從 Intel 80386 開始,出于安全性和穩(wěn)定性的考慮,CPU 可以運(yùn)行在 ring0 ~ ring3 四個(gè)不同的權(quán)限級(jí)別,也對(duì)數(shù)據(jù)提供相應(yīng)的四個(gè)保護(hù)級(jí)別。不過 Linux 和 Windows 只利用了其中的兩個(gè)運(yùn)行級(jí)別:
- 一個(gè)是內(nèi)核模式,對(duì)應(yīng) ring0 級(jí),操作系統(tǒng)的核心部分和設(shè)備驅(qū)動(dòng)都運(yùn)行在該模式下。
- 另一個(gè)是用戶模式,對(duì)應(yīng) ring3 級(jí),操作系統(tǒng)的用戶接口部分(例如 Windows API)以及所有的用戶程序都運(yùn)行在該級(jí)別。
為什么內(nèi)核和用戶程序要共用地址空間
既然內(nèi)核也是一個(gè)應(yīng)用程序,為何不讓它擁有獨(dú)立的4GB地址空間,而是要和用戶程序共享、占用有限的內(nèi)存呢?讓內(nèi)核擁有完全獨(dú)立的地址空間,就是讓內(nèi)核處于一個(gè)獨(dú)立的進(jìn)程中,這樣每次進(jìn)行系統(tǒng)調(diào)用都需要切換進(jìn)程。切換進(jìn)程的消耗是巨大的,不僅需要寄存器進(jìn)棧出棧,還會(huì)使CPU中的數(shù)據(jù)緩存失效、MMU中的頁表緩存失效,這將導(dǎo)致內(nèi)存的訪問在一段時(shí)間內(nèi)相當(dāng)?shù)托А?br />
而讓內(nèi)核和用戶程序共享地址空間,發(fā)生系統(tǒng)調(diào)用時(shí)進(jìn)行的是模式切換,模式切換僅僅需要寄存器進(jìn)棧出棧,不會(huì)導(dǎo)致緩存失效;現(xiàn)代CPU也都提供了快速進(jìn)出內(nèi)核模式的指令,與進(jìn)程切換比起來,效率大大提高了。
總結(jié)
- 上一篇: Linux下C语言程序的内存布局(内存模
- 下一篇: (char*)x C语言中的和*的详解