彭民德:《電子計算60年》 (19) UNIX核心反彙編程式碼有啃頭

彭民德發表於2016-08-24

UNIX第六版的程式畢竟是1974年的版本,時間已經過去10年了。它對於我們來說雖然還是全新的,但在國外已經有新的作業系統出來了,不能滿足於僅僅對UNIX第六版的分析,我們必須設法跟蹤最新的東西。當時手邊使用的機器是新買來的DUAL 68000微機,借摩托羅拉68000晶片命名。這種晶片單位面積上儲存68000個電晶體,當時用“芝麻粒上千條街”來形容整合度已經很高。機器還配了儲存管理部件MMU,硬體是很新的。軟體也好,其作業系統是UNIX 第七版,可以帶8臺終端,我們配了4臺,是一種多使用者機器。這款機器定位為微機,因為它跟以往的PDP等第三代機器相比,體積尺寸已經大為減小,就擺放在實驗桌上。但就其功能來說,具備一臺第三代多使用者機的全部特徵。

既然新版UNIX就工作在我們身邊,天天跟它打交道,能不能深入瞭解它的核心部分?作為一個新的版本,又有什麼新技術呢?

隨機資料只有厚厚的幾大本使用手冊,還是英文的,只告訴你怎麼去用它,不提供關於核心工作細節資料,更不提供原始碼。UNIX核心以檔案捲上一個單獨的UNIX.exe檔案駐留在磁碟上。因為是二進位制形式的,無法讀懂。從道理上知道在系統開機後會把這個檔案讀到記憶體,並讓它工作起來,管理整臺機器,提供使用者上機服務。

UNIX有一條支援閱讀可執行程式碼檔案的命令,可以把exe檔案內容以反彙編形式顯示出來。它相當於後來在MS-DOS環境下的debug,如果借用這個工具把UNIX的反彙編程式碼列印出來,是不是可以對程式碼做一些分析呢?

但是難度太大了。一個有幾百K位元組的exe檔案,又是已經把許多程式檔案和資料檔案裝配在一起的二進位制檔案,反彙編程式碼長度十分可觀,難以駕馭。反彙編出來的程式碼並不能保證跟原來的組合語言程式碼完全一致。最難的是經編譯和彙編並裝配之後的可執行程式,沒有符號變數,沒有可視形式資料結構,閱讀起來還沒準遇到無法預估的困難。

有幾個因素促使我們無論多麼困難,也要分析UNIX 核心第7版反彙編程式碼。一是有一個軟體(電算)專業高年級學生班(電算80),曾用一個學年144課時學習了作業系統原理,並分析了UNIX V6全部原始碼。期末考查題抽出main、newproc、sleep、iswtch等程式設問,問執行某個語句後,某個資料結構的內容;要求在給定條件下具體裝配程式的頁表; sleep怎樣保證呼叫程式放棄CPU,達到入睡目的;一個新程式被建立之後,有何舉措保證它或遲或早有機會執行,而不至於餓死;問不容易懂但很有內涵的2238行設定理由,“以表明你確實已加入2238行俱樂部”。“2238行俱樂部”一語來自於作者們寫的《UNIX程式碼註釋》對該行語句的註釋,它風趣地讓人閱讀程式碼儘可能輕鬆一些。考查得這樣細緻,說明我們分析程式碼具體而深入,學生們掌握得不錯。李舒揚同學還在接下來的一個寒假進一步閱讀,1984年春天給了我一份頗有見地的學習心得。我堅信像李舒揚、李建華等一批學生,對UNIX已有較深入認識。

二是這個班班風好,班幹部個個學習好,有能力有威信。這個班全面發展,體育活動也好,有班足球隊,系運動會班總分第一,韋春平的跳高成績在他畢業後10多年還保持為全校記錄。該班整體身心素質都好。

三是學生即將畢業而又不愁分配,他們都包分配,地點崗位都不錯,能夠集中精力於畢業設計。

這幾個條件隨便缺少哪一個,估計反彙編程式碼分析就不會搞。此時條件齊備,我們便下決心把全部程式碼列印出來,提出以此作為畢業設計課題。得到了老師支援,學生們歡迎。1984年上半年,電算80班級20位學生做畢業設計,分析UNIX第七版反彙編形式的程式碼。

反彙編形式的程式碼比源程式要長很多,而且要列印兩份,一份拆分給學生分析使用,每人至少也有上千行。另一份儲存完整形式為大家查詢公用。當時尚處在主要採用針式印表機的年代,摺疊式兩側有齒輪導孔的寬行列印紙,500頁一疊,要用好幾本。反彙編程式碼的列印工作量就很大,噪聲又討嫌。機房的老師和上機的師生們給予了大力支援,我們的分析工作才得以進行。

電子樓本班原來的專用教室,成了畢業設計專用教室。每人陸續找出資料和資料結構,理清模組呼叫關係。因為模組多,當時的UNIX採用的是非層次的模組結構,呼叫關係不是很容易搞得清的,必須多人多次常溝通。不但把黑板用上,還買來白紙書寫貼於牆上,教室裡都貼滿了。有的程式時不時往記憶體某個(片)地方讀或寫,那裡一定是某個資料結構。對第六版已有的認識無疑給我們奠定了基礎。

勞動得到了回報,工作是成功的。發現UNIX在保留原有主要技術和特色的同時,尺寸有較大幅度增加,有一些合理的改進,基本上搞清楚了新版本所做的這些改進。改進之處可以分為三類,一是為適應新的硬體而新加的部分,這也是程式尺寸增加的主要因素。比如,DUAL 68000直接定址能力較PDP-11/40從256KB達到16MB,採用了MOTOROLA 68451 MMU儲存管理部件,系統增加了一組管理MMU程式。新增加了軟盤驅動器,故增加了一組fdc管理程式。中斷與捕獲處理也因硬體不同而稍有不同。第二類是針對第六版的缺點,從自身效率方面的改進,這種改進貫穿於核心程式的每一部分。比如原先版本支援最多50個程式共存,新版本改為40個,排程起來效率會高一些。又比如原先就緒程式不排隊,排程時要考察所有就緒程式,而現在設立了就緒佇列,使排程快得多。第三類是為方便使用者使用的改進,比如系統呼叫從41條增至53條。

這些改進我們馬上歸納起來寫了“UNIX第七版核心的主要改進”一文(《計算機工程與應用》1984年第12期),跟同行們分享。該文1985年曾被評為鐵路高校優秀論文一等獎。

這次活動對每位參與者的學術能力是個很好的鍛鍊,這一收穫的意義甚至比理解了UNIX本身還要大。從人員的組織,小組劃分,把任務落實到個人,進度的協調,知識點的梳理和認識的統一,參考文獻的查閱,都得一步步進行。怎麼規劃自己的工作步驟,怎麼協作和協調,怎麼及時把別人的成果用到自己的工作上來,是不是要調整自己的工作計劃,等等,個個都得面對。每個學生寫的論文都像模像樣,可以說都站在當時作業系統領域的技術前沿。20人一起不分組畢業答辯,這樣可以交叉地聽,交叉提問。因為這是大家經過艱苦努力得到的認識,報告極其認真,事先都用白紙畫了程式流程圖和模組呼叫關係圖等。同學們的答辯會就是一個有深度的學術報告會。有些提問也很尖銳。比如
有人問鍾寧:甲程式啟動它的I/O後就睡眠了,當I/O完成後發生裝置中斷,被中斷的是當時執行的另一個乙程式。那麼乙程式利用自己的CPU時間幫甲程式做事,處理跟自己無關的裝置中斷。你認為這樣對於乙程式公平嗎?UNIX這種設計策略是不是有缺陷?
鍾寧回答:雖然乙程式幫甲程式處理了中斷,但乙程式的I/O中斷也是別的程式幫處理的。既然都要別人幫助,那就是互相幫助,也就公平了,UNIX的排程策略無可厚非。
答得巧妙和風趣。

(本文內容也可參看 彭民德《電子計算60年》第4章 電子工業出版社)

相關文章