課程實(shí)踐指南與XV6內(nèi)核解析)
1. 為什么選擇MIT 6.S081作為操作系統(tǒng)入門(mén)課第一次聽(tīng)說(shuō)MIT 6.S081這門(mén)課時(shí)我正在尋找一個(gè)能真正動(dòng)手實(shí)踐的操作系統(tǒng)課程。大多數(shù)傳統(tǒng)OS課程要么過(guò)于理論化要么實(shí)驗(yàn)環(huán)節(jié)只是簡(jiǎn)單調(diào)用現(xiàn)有API。而6.S081最吸引我的是它通過(guò)修改真實(shí)操作系統(tǒng)來(lái)學(xué)習(xí)的理念——課程基于XV6這個(gè)教學(xué)用操作系統(tǒng)所有實(shí)驗(yàn)都需要直接在內(nèi)核層面編寫(xiě)代碼。XV6是MIT為教學(xué)目的開(kāi)發(fā)的類Unix系統(tǒng)完整實(shí)現(xiàn)了進(jìn)程管理、文件系統(tǒng)等核心功能但代碼量控制在1萬(wàn)行左右Linux內(nèi)核超過(guò)2800萬(wàn)行。這個(gè)體量既保證了真實(shí)性又不會(huì)讓初學(xué)者望而生畏。我在完成第一個(gè)實(shí)驗(yàn)系統(tǒng)調(diào)用時(shí)就深刻體會(huì)到這種設(shè)計(jì)的好處雖然要直接修改內(nèi)核代碼但代碼結(jié)構(gòu)清晰關(guān)鍵函數(shù)都能在幾小時(shí)內(nèi)理清脈絡(luò)。2. 課程前置技能準(zhǔn)備清單2.1 編程語(yǔ)言要求課程所有實(shí)驗(yàn)都使用C和RISC-V匯編。我的C語(yǔ)言之前只停留在學(xué)校課程水平為此專門(mén)用兩周時(shí)間強(qiáng)化了以下知識(shí)點(diǎn)指針操作特別是函數(shù)指針和void*的使用結(jié)構(gòu)體和聯(lián)合體的內(nèi)存布局Makefile編寫(xiě)基礎(chǔ)GDB調(diào)試技巧后來(lái)發(fā)現(xiàn)這是救命技能RISC-V匯編部分不需要提前精通但建議了解基本指令集addi, ld, sd等寄存器約定a0-a7參數(shù)寄存器ra返回地址等棧幀結(jié)構(gòu)這對(duì)理解trap機(jī)制至關(guān)重要2.2 開(kāi)發(fā)環(huán)境搭建官方推薦在Linux環(huán)境下開(kāi)發(fā)。我嘗試過(guò)三種方案原生LinuxUbuntu 20.04最穩(wěn)定但需要雙系統(tǒng)Windows WSL2圖形界面支持較差調(diào)試麻煩MacOS Docker最終選擇的方案具體步驟# 安裝qemu和工具鏈 brew install riscv64-unknown-elf-gcc qemu # 克隆課程倉(cāng)庫(kù) git clone git://g.csail.mit.edu/xv6-labs-2020 cd xv6-labs-2020 make qemu第一次編譯可能會(huì)遇到工具鏈版本問(wèn)題需要調(diào)整Makefile中的TOOLPREFIX變量。3. 課程核心內(nèi)容與實(shí)驗(yàn)攻略3.1 課程知識(shí)圖譜整個(gè)課程圍繞XV6的七個(gè)核心子系統(tǒng)展開(kāi)系統(tǒng)調(diào)用與進(jìn)程管理Lab: syscall頁(yè)表與內(nèi)存管理Lab: page tables中斷與設(shè)備驅(qū)動(dòng)Lab: traps并發(fā)與鎖Lab: locks文件系統(tǒng)Lab: fs網(wǎng)絡(luò)棧Lab: net多核調(diào)度Lab: scheduler每個(gè)實(shí)驗(yàn)都對(duì)應(yīng)一個(gè)關(guān)鍵子系統(tǒng)難度呈階梯式上升。我的學(xué)習(xí)節(jié)奏是每周完成1個(gè)實(shí)驗(yàn)對(duì)應(yīng)課程視頻實(shí)際耗時(shí)約15-20小時(shí)/周。3.2 實(shí)驗(yàn)避坑指南在完成locks實(shí)驗(yàn)時(shí)我遇到過(guò)經(jīng)典的死鎖問(wèn)題在ide_lock之外獲取了sleep_lock導(dǎo)致磁盤(pán)中斷處理程序無(wú)法獲取ide_lock。解決方法是通過(guò)lock ordering原則統(tǒng)一鎖的獲取順序// 正確順序 acquire(ide_lock); acquire(sleep_lock);另一個(gè)常見(jiàn)問(wèn)題是系統(tǒng)調(diào)用實(shí)驗(yàn)中的寄存器傳參。RISC-V調(diào)用約定前8個(gè)參數(shù)通過(guò)a0-a7傳遞但內(nèi)核態(tài)需要通過(guò)trapframe獲取// 從用戶棧獲取第二個(gè)參數(shù) int arg1 p-trapframe-a1;4. 高效學(xué)習(xí)路徑規(guī)劃4.1 資源使用優(yōu)先級(jí)課程網(wǎng)站pdos.csail.mit.edu/6.S081/2020/包含所有實(shí)驗(yàn)說(shuō)明和講義XV6手冊(cè)xv6.dgs.mit.edu/相當(dāng)于XV6內(nèi)核說(shuō)明書(shū)課程視頻YouTube建議1.5倍速觀看社區(qū)討論P(yáng)iazza問(wèn)題基本都能找到答案4.2 時(shí)間管理技巧我采用三遍學(xué)習(xí)法第一遍快速瀏覽講義標(biāo)記不理解的概念第二遍結(jié)合視頻深入難點(diǎn)完成實(shí)驗(yàn)基礎(chǔ)部分第三遍挑戰(zhàn)實(shí)驗(yàn)的optional部分整理筆記對(duì)于復(fù)雜的文件系統(tǒng)實(shí)驗(yàn)建議畫(huà)出磁盤(pán)布局示意圖。這是我當(dāng)時(shí)繪制的簡(jiǎn)化圖[ boot block | super block | log | inodes | bitmap | data blocks ]5. 常見(jiàn)問(wèn)題解決方案5.1 調(diào)試技巧當(dāng)系統(tǒng)在qemu中崩潰時(shí)首先檢查使用make CPUS1 qemu-gdb啟動(dòng)調(diào)試在gdb中查看pc寄存器值info registers pc反匯編當(dāng)前位置x/10i $pc我曾用這個(gè)方法發(fā)現(xiàn)一個(gè)頁(yè)表錯(cuò)誤pc指向了0xdeadbeef原因是頁(yè)表項(xiàng)設(shè)置了非法權(quán)限位。5.2 測(cè)試方法論課程提供的測(cè)試用例往往不夠全面。建議為每個(gè)實(shí)驗(yàn)添加邊界測(cè)試如創(chuàng)建100個(gè)進(jìn)程并發(fā)測(cè)試多進(jìn)程同時(shí)操作共享資源錯(cuò)誤注入故意傳遞非法參數(shù)例如測(cè)試文件系統(tǒng)時(shí)可以編寫(xiě)腳本反復(fù)創(chuàng)建刪除文件for i in {1..100}; do echo $i testfile rm testfile done6. 學(xué)習(xí)效果檢驗(yàn)與進(jìn)階完成所有實(shí)驗(yàn)后我嘗試了三個(gè)拓展項(xiàng)目添加FAT32文件系統(tǒng)支持需要修改buf.c和file.c實(shí)現(xiàn)copy-on-write fork優(yōu)化內(nèi)存使用移植到真實(shí)硬件SiFive HiFive Unleashed開(kāi)發(fā)板這些項(xiàng)目不僅鞏固了課程知識(shí)還讓我理解了理論到實(shí)踐的完整閉環(huán)。比如在實(shí)現(xiàn)COW fork時(shí)需要深入理解頁(yè)表項(xiàng)的PTE_C標(biāo)志位設(shè)置這比單純完成課程實(shí)驗(yàn)收獲更大。