核心三章,第二卷:中斷返回

系統重啟後,所有的狀態都會丟失,除了那些寫在非易失性儲存裡的記憶。

本文原載於《2024秋冬季開源作業系統訓練營第一、二階段總結-catme0w》


來跟大夥嘮會

你們好,我是清朝老兵。

我是catme0w,你可能已經在排行榜見過我的名字了。

去年這個時候,我已經來過一次了。為什麼我會再來一次?馬上揭曉答案。

在繼續之前,你可以先看看我上一次留下的記錄:2023開源作業系統訓練營第二階段總結報告-CatMe0w

和上次一樣,我的日誌裡不會有太多關於技術的流水賬。如果你想看一個不錯的故事,那你來對地方了;如果你還在rCore中掙扎,正在尋找一些攻略,那麼我也不會讓你白跑一趟,接好了:

寫在最前,太長不看攻略:你可能需要的建議

  1. 強烈建議關閉Copilot或Codeium等程式碼補全器,它們完全無法理解核心,對於系統程式設計幾乎一無是處;它們產生出的程式碼會浪費你非常多的時間。
  2. 小黃鴨除錯法或許會有幫助。
  3. 在你100%理解程式碼庫之前,你是做不出題目的。相信我。
  4. 完全理解程式碼庫之後,先構思好你準備要做的東西,否則出場即大改。
  5. 做好因方向錯誤而大改的準備。
  6. 小心#[repr(C)]。
  7. rustsbi-qemu可能非常不穩定,遇到靈異現象?換個QEMU版本試試;如果你在用Apple Silicon,也換臺機器試試。
  8. gdb或許很低效,多插trace!()。

未講述的往事

如果你看了上邊我參加去年訓練營時的記錄,你應該已經瞭解到,當時,我在ch5就停滯下來然後退出了。我其實內心是有些後悔的,覺得自己當時並沒有看起來的那麼忙,是自己的懶惰造成不得不退出的結局。

縱使rCore從不是什麼大事,我還是覺得“抬不起頭”,之後也從未和別人再提起這個精緻的小作業系統,就好像未曾發生過。

我會自己寫一個作業系統嗎?也許永遠不會吧。就當是一場夢。我這麼想。


次年夏天。

在一個非常非常偶然的機會,我瞭解到我的一位朋友參加了今年春季的訓練營。而我們之間最大的不同,便是我自始至終都只抱著“60分萬歲”一般的態度,指望著能混到晉級就是勝利,而他從一開始的目標就是榜一。

我彷彿捱了一記響亮的耳光:做不到,只是因為不想。


所幸,訓練營從不禁止清朝老兵(而且現在還越來越多了!),我有機會為rCore重新補上一個完美結局。

rustlings II

我也是Rust老兵了,這100題,不是把我去年的補丁直接合過來便是?

然而從今年開始,rustlings多加了十道演算法題,成了110題。清朝老兵遇到了它的第一個障礙!

我瞭解Rust的脾氣,知道什麼資料結構得開unsafe,只是我已經很長時間沒有摸過演算法題了,更沒有用過Rust寫演算法題,一開啟,滿屏的泛型讓我虎軀一震。

這需要一點時間……不過,仍然只是小插曲。讓我們直面恐懼,走向rCore吧。

rCore II

實不相瞞,我去年壓根沒看懂rCore的教程,我的確是一路完成到了ch5,可除了ch3以外,我自己都不知道我寫了什麼東西,我的程式碼以一種連我自己都無法理解的方式執行起來,大概純粹是碰對了測例而已。

往好處想,將功補過的機會來了;往壞處想,這相當於一點經驗都沒有了!

ch3

沒有什麼困難,憑藉著清朝時期的記憶,我還記得ch3要在哪裡加上什麼。迅速結束戰鬥。

ch4

我至今都認為,ch4記憶體管理這一章是整個rCore難度最大的部分,至少在知識上是如此!題目本身反而是不那麼難的,程式碼量不大,理解記憶體管理的情況下應該很快能找到正確的路;可如果對記憶體模型有哪怕一丟丟一知半解,你都會在ch4的題目上擁有一段不愉快的時光。

嗯,我承認我是後者……

ch5

ch5做的是什麼來著?我又給忘了。它就是如此沒有存在感,前後的ch4和ch6都是令人大叫的程度,相比之下,ch5就有些難以給人留下深刻印象了。

哦想起來了是spawn。好像還真沒有太多可以說的,在經歷過前兩章的毒打之後,你應該能很快處理完這一章。

ch6

我抵達了我之前沒能征服的地方,硬骨頭來了。至此,rCore才真正展現出它的威力,BOSS進入二階段了!

ch6在知識上稍輕鬆些,但題目的難度卻和教材文字完全不成比例。題目的難點在於非常的繞,為了改動某個功能,你可能需要前後在許多不同的地方修改一連串程式碼,更不必提這個在核心之外的模組很難除錯。

到這裡,有件事我一定要罵:用Rust程式設計,有時真的很讓人沮喪。

人們總是說“編譯期攔住錯誤比事後debug更好”,可是隻有自己才知道,用Arc啊,Mutex啊那些東西的時候有多令人不快:它明明就在這裡,就是這麼直觀,但就是不讓你用。

當天中午11點,我已經幾乎完成了ch6的功能實現,我想著,ch6透過就去吃午飯。

你能猜到這樣立flag將會如何發展。

晚上11點的我:😅

ch8

就快結束了!最開始看到ch8教程的時候,我心中竊喜:這麼簡單啊!就好像回到了ch3一樣!

題目要求也很簡單,甚至詳盡地描述了要實現的每個細節。

上機開寫,很快就通過了互斥鎖的測例,訊號量的第一個測例也很快通過了。只剩最後一個測例了,馬上就可以結局了!

然後我就在這“最後一個測例上”卡了十多個小時。🌚

要麼是第一個測試不過,要麼是第二個,兩個測例呈現出完全不可理解的結果。可是無論我怎麼檢查自己的程式碼,在能插的地方都插滿了log,發現每個步驟確實都與預期中的相符,可為什麼結果就是不對呢?我也沒有理解錯題意啊?

“我也沒有理解錯題意”……等等。

會不會真是我把題目弄錯了?我會不會實現了一個錯誤的演算法?

走投無路之下,我開始直接寫這個演算法的證明,很快發現,(按我理解的)這個演算法根本無法檢測任何死鎖!

題目在演算法的描述上,確實有些混亂和容易誤導人。我意識到我該尋求外部資料了,到此時,我才終於知道這就是Dijkstra的銀行家演算法。

在查看了這個演算法的精確描述後,我才終於弄明白我出問題的地方:need矩陣,只減不增,更絕非我最初理解的從0開始增長。

終於,所有測例都能通過了,ch8結束了,可是我卻有些哭笑不得,因為這麼愚蠢和缺乏技術含量的原因卡住,感覺自己有些像是被戲弄了。

rCore EnCore

感謝你還有耐心看到這裡。也許你已經留意到,我在今年的排行榜上是榜一。

二階段classroom放出之後,我使用的是補丁方式提交,因而在補丁裡還留有當時的實際完成時間:9月21日。

在我完成rustlings之後,也就是今年報名剛開的那個週末,我把整個週末的全部時間都投入到速通rCore上了。

不為別的,我就想給去年的自己一個耳光。

尾聲

做rCore實驗的過程,前半程就是一籌莫展:你看了半天文件,感覺自己好像會了,一開啟程式碼卻發現兩眼一抹黑,根本不知道在幹什麼。

然後你花了很長時間終於大致摸清楚程式碼結構了,一準備開始寫,發現還是一籌莫展,都不知道要寫什麼東西。

過了不知道多久,終於你有了一個差不多的思路,可以開始寫了,此時,你來到了後半程。

你可能用了不太長的時間就寫出來,也可能很久,但一定是跑不起來的。

接下來你會用幾十個小時的時間去除錯,gdb或者插滿trace!()。

然而即使用了gdb也沒有太大幫助,因為錯誤往往出現在你想象不到的地方。

有的時候你會發現測試用例能過,甚至是隨機性可以過,有的時候會發現QEMU直接一動不動——rustsbi-qemu並不穩定。

當你第一次發現測試能過的時候,哪怕只是機率性成功,你以為自己離勝利近了,但你很快,或者很久以後才發現,方向完全錯了,你必須全部推倒重來。

這種事將會反覆發生。

最後,你離最終的目標越來越近,但每次都總差那麼一點,你不禁懷疑自己是否真的在接近終點,還是又一次搞錯了方向。

到了最後,你可能都記不清這中間到底推翻了多少次,改了多少個細節。你不再期待一蹴而就,而是學會了享受每次解決一個小問題的成就感。

不管失敗多少次,推倒多少次,你已經比一開始那個兩眼一抹黑的自己強太多了。也許方向錯了,程式碼推倒重來,但至少,你知道自己在進步,哪怕每一步都很艱難。最終你會發現,這些反覆掙扎的瞬間,才是整個過程裡最有價值的部分。

尾聲之後

“我會自己寫一個作業系統嗎?”

會的。


我回想起一件事,是在我很小的時候發生過的,我已經很難分辨究竟是什麼時候了。

人們在討論《30天自制作業系統》這本書。

當時的我想,啊,這竟然是可能的嗎?這本書一定很厚,很難懂……

在那時的我眼裡,除開最終呈現給使用者的應用程式,其餘關於計算機的一切都是魔法煙霧構成的黑盒——麻瓜弄不明白。

但在這麼多年之後,我終於明白,做不到,只是因為不想。

我們都可以。


訓練營只是一個開始,在這之後,還有更廣袤的世界等待著探索。

https://github.com/CatMe0w/attune