xv6book阅读 chapter2
一個操作系統(tǒng)至少應(yīng)該滿足三個需求:多路復(fù)用、隔離、交互。本章主要介紹如何組織操作系統(tǒng)來實(shí)現(xiàn)以上的三個需求,本文關(guān)注的是一種圍繞單核進(jìn)行設(shè)計(jì)的方法,這種設(shè)計(jì)是被許多uinx操作系統(tǒng)所使用的。Xv6運(yùn)行在多核RISC-V微處理器上時,它的許多低級功能(例如,它的進(jìn)程實(shí)現(xiàn))是特定于RISC-V的,RISC-V是一個64位的處理器,而xv6是用“LP64”C語言編寫的,這意味著C編程語言中的長(L)和指針(P)是64位,而int是32位,這里順便復(fù)習(xí)一下指針的大小是和機(jī)器有關(guān)的,比如64位機(jī)器中指針大小就是8字節(jié)。xv6是為qemu的“-machine virt”選項(xiàng)模擬的支持硬件編寫的。這包括RAM、包含引導(dǎo)代碼的ROM、與用戶鍵盤/屏幕的串行連接以及用于存儲的磁盤,而qemu所模擬的環(huán)境是單個CPU內(nèi)核。
1 抽象物理資源
為什么要有操作系統(tǒng)?操作系統(tǒng)可以做為一個系統(tǒng)調(diào)用的庫,被所有運(yùn)行在里面的程序所鏈接,而程序可以通過操作系統(tǒng)更好的使用硬件資源。通常進(jìn)程總是會有bug并且不能很好的信任彼此,因此需要很好的隔離性。隔離性不僅僅指進(jìn)程之間,還有進(jìn)程與資源,進(jìn)程與操作系統(tǒng)。
為了實(shí)現(xiàn)強(qiáng)隔離,禁止應(yīng)用程序直接訪問敏感的硬件資源,將資源抽象到服務(wù)中,是一種很好的方法。例如,Unix應(yīng)用程序僅通過文件系統(tǒng)的open、read、write和close系統(tǒng)調(diào)用與存儲交互,而不是直接讀寫磁盤。這樣一來,操作系統(tǒng)才是真正的資源管理者,而不是用戶。
2 用戶模式、管理者模式以及系統(tǒng)調(diào)用
強(qiáng)隔離要求應(yīng)用程序和操作系統(tǒng)之間有一個硬邊界。如果應(yīng)用程序出錯,我們不希望操作系統(tǒng)失敗,也不希望其他應(yīng)用程序失敗。操作系統(tǒng)應(yīng)該能夠清理失敗的應(yīng)用程序并繼續(xù)運(yùn)行其他應(yīng)用程序。為了實(shí)現(xiàn)強(qiáng)隔離,操作系統(tǒng)必須安排應(yīng)用程序不能修改(甚至讀取)操作系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)和指令,并且應(yīng)用程序的指令不能訪問其他進(jìn)程的內(nèi)存。這里其實(shí)就開始引出為什么要有用戶態(tài)和內(nèi)核態(tài)了。
cpu為強(qiáng)隔離提供硬件支持。例如,RISC-V有三種CPU執(zhí)行指令的模式:機(jī)器模式、管理者模式和用戶模式。在機(jī)器模式下執(zhí)行的指令具有完全權(quán)限;CPU以機(jī)器模式啟動。機(jī)器模式主要用于配置計(jì)算機(jī)。Xv6在機(jī)器模式下執(zhí)行幾行代碼,然后切換到管理者模式。
在管理者模式下,CPU被允許執(zhí)行特權(quán)指令:例如,啟用和禁用中斷,讀取和寫入保存頁表地址的寄存器,等等。如果用戶模式下的應(yīng)用程序試圖執(zhí)行特權(quán)指令,則CPU不會執(zhí)行該指令,而是切換到管理者模式,以便管理者模式代碼可以終止應(yīng)用程序,因?yàn)樗隽艘恍┎粦?yīng)該做的事情。應(yīng)用程序只能執(zhí)行用戶模式指令(例如,添加數(shù)字等),被稱為在用戶空間中運(yùn)行,而處于管理者模式的軟件也可以執(zhí)行特權(quán)指令,被稱為在內(nèi)核空間中運(yùn)行。在內(nèi)核空間(或在管理器模式下)運(yùn)行的軟件稱為內(nèi)核。
上述三種模式是針對于CPU的,對于程序而言,它所執(zhí)行的環(huán)境可以分為用戶態(tài)和內(nèi)核態(tài),對應(yīng)著CPU的用戶模式和管理者模式。一個想要調(diào)用內(nèi)核函數(shù)的應(yīng)用程序(例如,在xv6中讀取系統(tǒng)調(diào)用)必須轉(zhuǎn)換到內(nèi)核態(tài)。CPU通常會提供一個特殊的指令,可以將CPU從用戶模式切換到管理模式,并在內(nèi)核指定的入口點(diǎn)進(jìn)入內(nèi)核。(RISC-V為此目的提供了調(diào)用指令ecall)。
一旦CPU切換到管理者模式,內(nèi)核就可以驗(yàn)證系統(tǒng)調(diào)用的參數(shù)(例如,檢查傳遞給系統(tǒng)調(diào)用的地址是否屬于應(yīng)用程序內(nèi)存的一部分),決定是否允許應(yīng)用程序執(zhí)行請求的操作(例如,檢查是否允許應(yīng)用程序?qū)懭胫付ǖ奈募?,然后拒絕它或執(zhí)行它。重要的是,內(nèi)核會控制過渡到管理器模式的入口點(diǎn),否則惡意程序也可以隨意進(jìn)入內(nèi)核態(tài)
3 內(nèi)核架構(gòu)
一個關(guān)鍵的設(shè)計(jì)問題是操作系統(tǒng)的哪個部分應(yīng)該在管理者模式下運(yùn)行。一種實(shí)現(xiàn)是整個操作系統(tǒng)駐留在內(nèi)核中,因此所有系統(tǒng)調(diào)用的實(shí)現(xiàn)都以管理者模式運(yùn)行。這種組織稱為宏內(nèi)核(a monolithic kernel)。
在這種組織中,整個操作系統(tǒng)以完全硬件特權(quán)運(yùn)行。這種組織很方便,因?yàn)椴僮飨到y(tǒng)設(shè)計(jì)者不必決定操作系統(tǒng)的哪一部分不需要完全的硬件特權(quán)。此外,操作系統(tǒng)的不同部分更容易協(xié)作。例如,一個操作系統(tǒng)可能有一個緩沖緩存,它可以被文件系統(tǒng)和虛擬內(nèi)存系統(tǒng)共享。
但宏內(nèi)核的缺點(diǎn)就是操作系統(tǒng)中不同部分之間的接口設(shè)計(jì)很復(fù)雜,并且宏內(nèi)核中產(chǎn)生的任何一個錯誤都是致命的,因?yàn)楣芾碚吣J街械腻e誤通常都會導(dǎo)致cpu運(yùn)行失敗,這個時候必須重啟才行。
為了減少在內(nèi)核中出錯的風(fēng)險(xiǎn),操作系統(tǒng)設(shè)計(jì)者可以盡量減少在管理者模式下運(yùn)行的操作系統(tǒng)代碼的數(shù)量,并在用戶模式下執(zhí)行大部分操作系統(tǒng)。這種內(nèi)核組織稱為微內(nèi)核。
在圖中,文件系統(tǒng)作為用戶級進(jìn)程運(yùn)行。作為進(jìn)程運(yùn)行的操作系統(tǒng)服務(wù)稱為服務(wù)器。為了允許應(yīng)用程序與文件服務(wù)器交互,內(nèi)核提供了一個進(jìn)程間通信機(jī)制,將消息從一個用戶模式進(jìn)程發(fā)送到另一個用戶模式進(jìn)程。例如,如果像shell這樣的應(yīng)用程序想要讀取或?qū)懭胛募鼤蛭募?wù)器發(fā)送消息并等待響應(yīng)。
但無論是微內(nèi)核還是宏內(nèi)核,都是有很多相似的設(shè)計(jì)思想,比如它們都會有系統(tǒng)調(diào)用,處理中斷、支持進(jìn)程,支持鎖,實(shí)現(xiàn)文件系統(tǒng)等。Xv6是作為一個宏內(nèi)核實(shí)現(xiàn)的,因此,xv6內(nèi)核接口對應(yīng)于操作系統(tǒng)接口,內(nèi)核實(shí)現(xiàn)完整的操作系統(tǒng)。
4 內(nèi)核的文件組織
xv6內(nèi)核源代碼位于“kernel/”子目錄下。源代碼按照模塊化的方式粗略劃分為多個文件,如下圖所示,模塊間的接口定義在kernel/defs.h中
5 進(jìn)程概述
進(jìn)程是xv6內(nèi)核中最小的隔離單位,內(nèi)核用來實(shí)現(xiàn)進(jìn)程的機(jī)制包括用戶/主管模式標(biāo)志、地址空間和線程的時間切片。Xv6使用頁表(由硬件實(shí)現(xiàn))為每個進(jìn)程提供自己的地址空間。RISC-V頁表轉(zhuǎn)換(或“映射”)一個虛擬地址(RISC-V指令操作)到一個物理地址(CPU芯片發(fā)送到主存的地址)。
xv6為每個進(jìn)程維護(hù)一個單獨(dú)的頁表,用于定義該進(jìn)程的地址空間。地址空間包括從虛擬地址0開始的進(jìn)程用戶內(nèi)存,如下圖所示。首先是指令,然后是全局變量,然后是堆棧,最上面有兩個特殊的區(qū)域trapframe和trampoline,這里對其分別解釋一下:
1.trapframe:
-
trapframe是一個數(shù)據(jù)結(jié)構(gòu),用于保存處理中斷或異常時 CPU 寄存器的狀態(tài)。它記錄了中斷或異常發(fā)生時,CPU 寄存器的值,以及一些其他與處理中斷相關(guān)的信息。以便在中斷服務(wù)例程(interrupt service routine,ISR)執(zhí)行完畢后,能夠正確地恢復(fù)進(jìn)程的執(zhí)行。 - trapframe 中的信息可能包括程序計(jì)數(shù)器(PC)、堆棧指針(SP)、標(biāo)志寄存器(FLAGS)、各種段寄存器等。
2.trampoline:
-
trampoline是一段代碼,通常是匯編代碼,用于在用戶態(tài)和內(nèi)核態(tài)之間進(jìn)行切換。當(dāng)中斷或異常發(fā)生時,CPU 需要從用戶態(tài)切換到內(nèi)核態(tài),執(zhí)行內(nèi)核中對應(yīng)的中斷服務(wù)例程。trampoline 代碼的作用是協(xié)助這個切換過程。 - 在 xv6 中,trampoline 代碼的一部分被放置在用戶地址空間中,以便在用戶程序發(fā)生中斷時,能夠正確地切換到內(nèi)核態(tài)執(zhí)行中斷服務(wù)例程。
RSIC-V處理器上的指針是64位的,但在頁表中查找虛擬地址的時候,硬件只使用低39位,因此進(jìn)程空間的最大地址只能是2^38-1,對于最大地址空間的宏定義為MAXVA(kernel/riscv.h:363)
xv6內(nèi)核為每個進(jìn)程維護(hù)一個proc結(jié)構(gòu)體,用于保存進(jìn)程的一些狀態(tài)信息
(kernel/proc.h:86)。進(jìn)程最重要的內(nèi)核狀態(tài)信息是他的頁表、堆棧和運(yùn)行狀態(tài)。可以使用p->xxx來指代proc結(jié)構(gòu)體的元素,如p->pagetable是指向進(jìn)程頁表的指針。
每個進(jìn)程都有一個用于執(zhí)行指令的上下文。這個上下文包括進(jìn)程的寄存器狀態(tài)、程序計(jì)數(shù)器(PC)以及其他與執(zhí)行指令相關(guān)的信息。每個進(jìn)程都在自己的地址空間中執(zhí)行,有獨(dú)立的寄存器狀態(tài)和代碼空間。而xv6book中所指的執(zhí)行線程可以理解為上下文中可以執(zhí)行指令的組成部分。每個進(jìn)程有兩個堆棧:用戶堆棧和內(nèi)核堆棧(p->kstack)。當(dāng)進(jìn)程執(zhí)行用戶指令時,只有它的用戶堆棧在使用,而它的內(nèi)核堆棧是空的。當(dāng)進(jìn)程進(jìn)入內(nèi)核時(對于系統(tǒng)調(diào)用或中斷),內(nèi)核代碼在進(jìn)程的內(nèi)核堆棧上執(zhí)行;當(dāng)進(jìn)程處于內(nèi)核中時,它的用戶堆棧仍然包含保存的數(shù)據(jù),但是沒有被積極使用。進(jìn)程的線程在主動使用其用戶堆棧和內(nèi)核堆棧之間交替。內(nèi)核堆棧是獨(dú)立的(并且不受用戶代碼的影響),因此即使進(jìn)程破壞了它的用戶堆棧,內(nèi)核也可以執(zhí)行。
進(jìn)程可以通過執(zhí)行RISC-V調(diào)用指令來進(jìn)行系統(tǒng)調(diào)用。該指令提高硬件特權(quán)級別,并將程序計(jì)數(shù)器更改為內(nèi)核定義的入口點(diǎn)。入口點(diǎn)的代碼切換到內(nèi)核堆棧,并執(zhí)行實(shí)現(xiàn)系統(tǒng)調(diào)用的內(nèi)核指令。當(dāng)系統(tǒng)調(diào)用完成時,內(nèi)核切換回用戶堆棧,并通過調(diào)用sret指令返回到用戶空間,這降低了硬件特權(quán)級別,并在系統(tǒng)調(diào)用指令之后恢復(fù)執(zhí)行用戶指令。進(jìn)程的執(zhí)行線程可以在內(nèi)核中“阻塞”以等待I/O,并在I/O完成后恢復(fù)到它離開的地方。
p->state用于指示線程是在運(yùn)行態(tài)、就緒態(tài)還是阻塞態(tài),p->pagetable指示進(jìn)程的頁表,當(dāng)在用戶空間中執(zhí)行進(jìn)程時,xv6的分頁硬件會使用該頁表。而一個進(jìn)程的頁表不僅用于映射虛擬地址到物理地址,同時也記錄了分配給該進(jìn)程存儲內(nèi)存的物理頁面的地址。
總而言之,一個進(jìn)程捆綁了兩個設(shè)計(jì)思想:一個地址空間,給進(jìn)程一個自己內(nèi)存的錯覺;一個執(zhí)行線程,給進(jìn)程一個自己CPU的錯覺。在xv6中,一個進(jìn)程由一個地址空間和一個線程組成。在實(shí)際操作系統(tǒng)中,一個進(jìn)程可能有多個線程來利用多個cpu。
總結(jié)
以上是生活随笔為你收集整理的xv6book阅读 chapter2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RocketMQ事务消息在订单创建和库存
- 下一篇: 携程OceanBase开源实践——索引统