文艷軍,羅 宇,李?yuàn)檴?,劉江?/p>
(國(guó)防科技大學(xué) 計(jì)算機(jī)學(xué)院,湖南 長(zhǎng)沙 410073)
操作系統(tǒng)實(shí)驗(yàn)設(shè)計(jì)的一個(gè)難點(diǎn)問題是如何使學(xué)生比較容易地掌握操作系統(tǒng)內(nèi)核的工作過(guò)程,從而真正弄懂內(nèi)核。目前學(xué)界的操作系統(tǒng)內(nèi)核實(shí)驗(yàn)設(shè)計(jì)主要有以下幾種做法。
(1)要求學(xué)生從一個(gè)基本框架出發(fā),逐步開發(fā)出一個(gè)基本可用的操作系統(tǒng),例如MIT的6.828課程使用JOS操作系統(tǒng),伯克利加州大學(xué)的CS162課程使用Pintos操作系統(tǒng),哈佛大學(xué)的CS161課程使用OS/161操作系統(tǒng),清華大學(xué)使用ucore操作系統(tǒng),浙江大學(xué)使用Lcore操作系統(tǒng)[1]等。
(2)要求學(xué)生對(duì)一個(gè)已經(jīng)基本可用的操作系統(tǒng)進(jìn)行分析、改寫或擴(kuò)充。例如MIT的6.828課程同時(shí)使用xv6操作系統(tǒng),荷蘭阿姆斯特丹Vrije大 學(xué) 的Andrew S.Tanenbaum使 用MINIX 3, 哈爾濱工業(yè)大學(xué)的李治軍等使用Linux 0.11操作系統(tǒng)[2],北京英真時(shí)代科技有限公司開發(fā)的操作系統(tǒng)課程也使用Linux 0.11操作系統(tǒng)[3]。本教 學(xué)組也在Linux 0.11上開發(fā)過(guò)一組內(nèi)核調(diào)試分析實(shí)驗(yàn)[4]。
(3)要求學(xué)生對(duì)一個(gè)商用級(jí)別的操作系統(tǒng)進(jìn)行分析或改寫。例如西安郵電大學(xué)的陳莉君等使用高版本Linux[5],以前也有一些學(xué)校使用Open Solaris和WRK[6]。典型做法是增加內(nèi)核模塊和驅(qū)動(dòng)程序等。
上述探索有力地促進(jìn)了學(xué)生對(duì)操作系統(tǒng)內(nèi)核的掌握,成效顯著。與此同時(shí),降低難度與取得整體性認(rèn)識(shí)難以兩全。從基本框架出發(fā)寫出一個(gè)可用操作系統(tǒng)難度大,尤其在開始階段,需要首先掌握大量CPU編程細(xì)節(jié),導(dǎo)致啟動(dòng)門檻高,學(xué)習(xí)曲線陡峭。分析改寫一個(gè)已經(jīng)基本可用的操作系統(tǒng)或者商用級(jí)操作系統(tǒng)又很難獲得整體性認(rèn)識(shí),因?yàn)橄到y(tǒng)已經(jīng)很復(fù)雜了:xv6有近1萬(wàn)行代碼,Linux 0.11有近15000行代碼,Linux 4.4則有近2000萬(wàn)行代碼。本教學(xué)組大規(guī)模使用調(diào)試手段分析內(nèi)核特定路徑,有助于降低難度并取得較好的整體性認(rèn)識(shí)。但在以前的設(shè)計(jì)中,對(duì)一條執(zhí)行路徑只分析一次,直接分析該路徑上詳細(xì)的狀態(tài)變化,一次暴露所有細(xì)節(jié)。這導(dǎo)致依然存在需要首先掌握大量CPU編程和操作系統(tǒng)設(shè)計(jì)細(xì)節(jié)、啟動(dòng)門檻高的問題。
抽象精化思想在程序分析和驗(yàn)證領(lǐng)域有廣泛應(yīng)用[7],基于內(nèi)核調(diào)試和抽象精化的操作系統(tǒng)實(shí)驗(yàn)設(shè)計(jì)方法的基本思想是:對(duì)每條內(nèi)核執(zhí)行路徑分析多遍,分析時(shí)不一次暴露所有細(xì)節(jié),而是進(jìn)行抽象,一開始只觀察少量細(xì)節(jié),即作一個(gè)高層抽象,在后面再次分析時(shí)逐漸加入更多細(xì)節(jié),對(duì)抽象進(jìn)行精化、降低抽象程度,逐步貼近完整的復(fù)雜底層狀態(tài),見圖1。
內(nèi)核實(shí)驗(yàn)主要圍繞兩條內(nèi)核執(zhí)行路徑展開,其目的是使內(nèi)核執(zhí)行一些特定的功能模塊,滿足實(shí)驗(yàn)內(nèi)容需要。路徑1見圖2,修改了內(nèi)核main函數(shù)(部分),針對(duì)的是中斷與異常、進(jìn)程管理和內(nèi)存管理等內(nèi)核功能。按此路徑運(yùn)行時(shí),內(nèi)核會(huì)創(chuàng)建兩個(gè)進(jìn)程:0號(hào)進(jìn)程和1號(hào)進(jìn)程,分別循環(huán)輸出字符‘0’和字符‘1’。運(yùn)行時(shí),會(huì)先執(zhí)行0號(hào)進(jìn)程(圖2的軌跡‘1’),然后切換到1號(hào)進(jìn)程(軌跡‘2’),再切換回0號(hào)進(jìn)程(軌跡‘3’),最后在時(shí)鐘中斷處理時(shí)切換到1號(hào)進(jìn)程(軌跡‘4’)。這條路徑涉及段頁(yè)式內(nèi)存管理、用戶態(tài)與核心態(tài)的相互轉(zhuǎn)換、fork系統(tǒng)調(diào)用、時(shí)鐘中斷處理、進(jìn)程調(diào)度和進(jìn)程切換等知識(shí)點(diǎn)。
圖2 內(nèi)核執(zhí)行路徑1
路徑2見圖3,只修改了內(nèi)核init函數(shù),針對(duì)的是設(shè)備管理和文件系統(tǒng)等內(nèi)核功能。按此路徑運(yùn)行時(shí),內(nèi)核也會(huì)創(chuàng)建兩個(gè)進(jìn)程:0號(hào)進(jìn)程和1號(hào)進(jìn)程,0號(hào)進(jìn)程空轉(zhuǎn),1號(hào)進(jìn)程會(huì)執(zhí)行init函數(shù),先加載根文件系統(tǒng)(代碼塊‘1’),然后打開控制臺(tái)終端(代碼塊‘2’),接著輸出提示信息并等待用戶輸入(代碼塊‘3’),再將文件/usr/root/hello.c的內(nèi)容讀出、顯示,并寫到文件/usr/root/hello-new.c中(代碼塊‘4’),最后執(zhí)行同步操作,將修改過(guò)的內(nèi)存緩沖區(qū)內(nèi)容寫入外存(代碼塊‘5’)。這條路徑涉及字符設(shè)備、塊設(shè)備和普通文件的打開、關(guān)閉和讀寫等知識(shí)點(diǎn),也在一定程度上涉及路徑1的知識(shí)點(diǎn)。
實(shí)驗(yàn)時(shí),學(xué)生將沿著這兩條路徑對(duì)Linux內(nèi)核進(jìn)行調(diào)試,觀察CPU寄存器和內(nèi)存的狀態(tài)變化,并進(jìn)而對(duì)內(nèi)核進(jìn)行部分改寫。我們建立了方便的實(shí)驗(yàn)環(huán)境,利用Bochs虛擬機(jī)軟件的調(diào)試功能,可以在Ubuntu中對(duì)內(nèi)核進(jìn)行源碼級(jí)(使用gdb)和匯編級(jí)調(diào)試(使用bochdbg)。
圖3 內(nèi)核執(zhí)行路徑2
基于操作系統(tǒng)原理課程設(shè)計(jì)了5個(gè)內(nèi)核實(shí)驗(yàn),分別與教材[8]的第2、3、5、6、7章配套。在原理授課時(shí),同步講授實(shí)驗(yàn)原理,引導(dǎo)學(xué)生進(jìn)行調(diào)試分析,要求學(xué)生在課外對(duì)內(nèi)核進(jìn)行深入的調(diào)試分析和改寫,同步完成實(shí)驗(yàn)。這些實(shí)驗(yàn)的基本情況見表1。
這些實(shí)驗(yàn)覆蓋了操作系統(tǒng)內(nèi)核的各主要模塊,每個(gè)實(shí)驗(yàn)的內(nèi)容包括調(diào)試分析和改寫兩部分,具體見表2。
三個(gè)實(shí)驗(yàn)的分析對(duì)象是內(nèi)核執(zhí)行路徑1,后兩個(gè)實(shí)驗(yàn)的分析對(duì)象是內(nèi)核執(zhí)行路徑2。
正如前文所述,為了降低難度、使學(xué)習(xí)曲線更平滑,采用抽象精化思想來(lái)設(shè)計(jì)這些實(shí)驗(yàn)。在完成這些實(shí)驗(yàn)時(shí),需要學(xué)生關(guān)注的狀態(tài)信息是由少逐步變多的,調(diào)試時(shí)不用看懂所有細(xì)節(jié),只需弄懂要求的部分信息即可。具體而言,每個(gè)實(shí)驗(yàn)關(guān)注的狀態(tài)信息主要包括3類:CPU寄存器、操作系統(tǒng)內(nèi)核數(shù)據(jù)結(jié)構(gòu)、操作系統(tǒng)內(nèi)核的函數(shù)調(diào)用事件,具體見表3。
其中‘+’表示在前序?qū)嶒?yàn)關(guān)注狀態(tài)信息的基礎(chǔ)上再增加一些信息,當(dāng)然不一定所有前序信息都需要在本實(shí)驗(yàn)中觀察,但總體而言觀察的信息是遞增的。以CPU寄存器為例,4個(gè)特殊段寄存器(IDTR、GDTR、TR、LDTR)是在前3個(gè)實(shí)驗(yàn)中逐步引入的,其中涉及的復(fù)雜段頁(yè)式地址轉(zhuǎn)換過(guò)程被逐步介紹,難度得到分解。完成前3個(gè)實(shí)驗(yàn)后,X86 CPU的特殊寄存器就基本介紹完了。
正是因?yàn)椴捎昧诉@種抽象精化的思想,復(fù)雜性被逐步引入,當(dāng)學(xué)生完成所有5個(gè)實(shí)驗(yàn)后,對(duì)Linux 0.11內(nèi)核的掌握已經(jīng)很深入了。
表1 實(shí)驗(yàn)概況
本實(shí)驗(yàn)方案在國(guó)防科技大學(xué)計(jì)算機(jī)學(xué)院2018年秋的操作系統(tǒng)原理課中進(jìn)行了實(shí)施,實(shí)驗(yàn)與原理課同步開展。班上共27名學(xué)生,所有學(xué)生都達(dá)到了及格標(biāo)準(zhǔn),且優(yōu)秀和良好的學(xué)生占了絕大多數(shù)。
表3 各實(shí)驗(yàn)關(guān)注的狀態(tài)信息
此外,課程結(jié)束后進(jìn)行了匿名問卷調(diào)查,收到關(guān)于實(shí)驗(yàn)難度的反饋25份,其中反映“實(shí)驗(yàn)容易,需要增加難度”的有1人,反映“實(shí)驗(yàn)難度適中,不用增加難度”的有21人,反映“實(shí)驗(yàn)難,應(yīng)該降低一些難度”的有3人。
綜合來(lái)看,按照本實(shí)驗(yàn)設(shè)計(jì)方案,在保證較好的實(shí)驗(yàn)深度的同時(shí),內(nèi)核實(shí)驗(yàn)的難度得到了有效控制。
同時(shí),該模式存在一些有待改進(jìn)的地方:部分能力強(qiáng)的學(xué)生希望提高內(nèi)核改寫的規(guī)模和難度。可以考慮為這類學(xué)生設(shè)計(jì)更具挑戰(zhàn)性的內(nèi)核實(shí)驗(yàn)。
這種基于調(diào)試分析和抽象精化的操作系統(tǒng)內(nèi)核實(shí)驗(yàn)設(shè)計(jì)方法,設(shè)計(jì)了一組Linux 0.11內(nèi)核調(diào)試分析與改寫實(shí)驗(yàn),并在操作系統(tǒng)課中進(jìn)行了試驗(yàn),取得了良好效果,內(nèi)核實(shí)驗(yàn)的難度得到分解,啟動(dòng)門檻降低。后續(xù)工作將針對(duì)不同基礎(chǔ)的學(xué)生設(shè)計(jì)一些可選實(shí)驗(yàn),進(jìn)一步完善實(shí)驗(yàn)設(shè)計(jì)方案。