




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
文件系統(tǒng)實(shí)習(xí)報(bào)告姓名李煒學(xué)號1100012810日期5月6日
目錄內(nèi)容一:總體概述 3內(nèi)容二:任務(wù)完成情況 3任務(wù)完成列表(Y/N) 3具體Exercise的完成情況 3內(nèi)容三:遇到的困難以及解決方法 4內(nèi)容四:收獲及感想 5內(nèi)容五:對課程的意見和建議 5內(nèi)容六:參考文獻(xiàn) 5內(nèi)容一:總體概述這次實(shí)習(xí)都過擴(kuò)展文件系統(tǒng)以及添加相應(yīng)的系統(tǒng)調(diào)用,幫助我們理解文件在磁盤中實(shí)際的存儲方式,目錄、文件頭和文件之間的關(guān)系,以及控制臺和文件讀寫之間的關(guān)系。概念主要涉及到了inode的實(shí)現(xiàn)方式,多級索引,多級目錄等。【用簡潔的語言描述本次lab的主要內(nèi)容;闡述本次lab中涉及到的重要的概念,技術(shù),原理等,以及其他你認(rèn)為的最重要的知識點(diǎn)。這一部分主要是看大家對lab的總體的理解。 要求:簡潔,不需要面面俱到,把重要的知識點(diǎn)闡述清楚即可?!績?nèi)容二:任務(wù)完成情況任務(wù)完成列表(Y/N)Exercise1Exercise2Exercise3Exercise4Exercise5Exercise6第一部分YYYYY第二部分YYY第三部分YYchallengeYNNY具體Exercise的完成情況第一部分:文件系統(tǒng)的基本操作Exercise1:Filesys.hfilesys.cc從filesys.h的注釋中,我們可以看到,nachos使用了兩套文件系統(tǒng),一個(gè)是基于unix(linux)本身的文件系統(tǒng)的類似于包裝函數(shù),另一個(gè)是需要我們實(shí)現(xiàn)的真正的文件系統(tǒng),現(xiàn)在的nachos文件系統(tǒng)有很多限制,比如說,這個(gè)文件系統(tǒng)不支持多層的文件目錄,而是只有root目錄,而且由于系統(tǒng)啟動的限制,標(biāo)記磁盤使用情況的bitmap和目錄分別在sector0,sector1。這樣就限制了可以使用的磁盤的大小和可以創(chuàng)建的文件的數(shù)量,就像其它大多數(shù)文件系統(tǒng)一樣,nachos需要支持初始化文件系統(tǒng),創(chuàng)建文件,打開文件,刪除文件,打印目錄中的文件,打印文件信息。而這個(gè)文件系統(tǒng)中關(guān)鍵的數(shù)據(jù)結(jié)構(gòu)就是前面所說的空閑區(qū)表,和根目錄。下面具體來看需要實(shí)現(xiàn)的這些函數(shù)的初步實(shí)現(xiàn)。創(chuàng)建文件系統(tǒng)的時(shí)候首先查看是不是已經(jīng)被“格式化”了,也就是是不是已經(jīng)存在了文件系統(tǒng),如果不存在的話,那么先要創(chuàng)建并初始化前面經(jīng)常提到的bitmap和目錄,而因?yàn)檫@兩個(gè)數(shù)據(jù)結(jié)構(gòu)本身也需要存儲在文件中,所以首先標(biāo)記宏定義的0號和1號sector是已經(jīng)被占用了的,但是在nachos中實(shí)際上bitmap和根目錄也是文件,同樣需要文件頭來管理,于是0號和1號實(shí)際上存儲的分別是bitmap和根目錄的文件頭,而真正的bitmap和根目錄需要文件頭接著使用allocate函數(shù)來分配,并且writeback,向分配出的兩個(gè)塊寫回到文件中,完成之后,打開這兩個(gè)文件并將初始化后的bitmap和目錄寫入到這兩個(gè)文件。如果文件系統(tǒng)已經(jīng)存在的話,那么直接new出兩個(gè)結(jié)構(gòu)即可,之后的操作可以直接使用文件中的信息了。對于創(chuàng)建文件來說,步驟如下,首先確保同目錄下不存在同名文件,之后為文件頭分配磁盤塊(只有一個(gè)塊),為文件實(shí)際的數(shù)據(jù)分配磁盤空間,向目錄中加入這個(gè)文件名,將文件頭寫入到磁盤中,刷新bitmap和目錄信息到磁盤中的這兩個(gè)文件中。對于打開文件來說,只需要打開目錄文件,找到具有給出的名字的文件,然后打開這個(gè)文件即可。對于刪除文件來說,需要從目錄中去掉這一項(xiàng),刪掉文件頭在磁盤上占用的塊,刪掉文件數(shù)據(jù)占據(jù)的塊,將bitmap和目錄的變化寫回磁盤。Filehdr.hfilehdr.cc這兩個(gè)文件和前面提到的文件頭有關(guān),也就是原理課上講到過的i-node,從頭文件中可以看出,文件的頭存儲的全部是直接索引(占用的文件塊號),這就限定了文件的大小目前不能超過4K,而且還有一點(diǎn)很重要的是,每個(gè)文件頭都只能占用一個(gè)塊,這就限制了文件頭中能夠存儲的文件的信息。除此之外,文件頭鎖存儲的信息十分有限,只有文件的大?。╞ytes)和占用的sector多少。對于其中的功能來說,allocate通過向bitmap不斷申請磁盤塊(直到足夠?yàn)橹梗瑏慝@得文件所需要的空間,而deallocate則正好相反,通過將datasectors中的所有磁盤塊還原為未使用來釋放空間。其它函數(shù)都很簡單,基本上是對synchdisk的包裝函數(shù),這里就不介紹了。Directory.hdirectory.cc對于目錄來說,其實(shí)就是許多文件名和文件頭所在塊的組合,這個(gè)組合被定義為一個(gè)叫做DirectoryEntry的類,這個(gè)類中除了包含這兩個(gè)信息之外,還包括目錄項(xiàng)是否被使用。而對于這個(gè)目錄來說,最主要的數(shù)據(jù)結(jié)構(gòu)就是table(DirectorEntry數(shù)組)。下面來看具體的函數(shù),對于構(gòu)造函數(shù)來說,就是創(chuàng)建出上面所說的table,并且初始化。FetchFrom的作用是從已經(jīng)有了目錄結(jié)構(gòu)的文件中,把這個(gè)結(jié)構(gòu)整體讀到table中。writeBack則相反,是將table的內(nèi)容寫入到一個(gè)文件中。FindIndex是通過文件名來查找這個(gè)文件在table中的索引號。Find則是通過先找到索引號,之后返回文件所對應(yīng)的文件頭的塊號。Add是通過檢查目錄中是否有重名文件或者目錄是否仍有空間,如果是的話就把這個(gè)文件名-文件頭塊號對寫入到table當(dāng)中。Remove十分簡單,把table中對應(yīng)的這一項(xiàng)的inUse設(shè)置成False(原來inUse是標(biāo)記是不是有效的,現(xiàn)在才看出來)。OpenFile.hopenFile.cc和filesys一樣,openfile也有兩種實(shí)現(xiàn),一種是unix的包裝,令一種是需要我們自己去改進(jìn)的簡單的打開文件的方式??梢钥闯?,對于一個(gè)打開文件操作來說,最重要的是文件頭和當(dāng)前讀到的位置,對應(yīng)的就是hdr和seekPosition,下面來看具體的函數(shù)。構(gòu)造函數(shù)的作用是從一個(gè)sector中讀入文件頭,并且把讀取位置設(shè)置成0。Read和write差不多,都是從當(dāng)前位置開始讀制定長度的內(nèi)容到into指向的位置,使讀取位置這個(gè)值增加到讀到的位置,并且返回真正讀取到的字節(jié)數(shù)。Readat函數(shù)將文件從指定的位置向后讀指定長度(如果夠長的話), 但是不同的是讀取文件位置的指不變,先是讀文件到一個(gè)buf緩沖數(shù)組中,之后從buf中再復(fù)制到into指定的位置。Exercise2:擴(kuò)展文件信息,我選擇在文件頭中添加文件信息(也可以在目錄中添加),對于文件類型來說,我在filehdr中新定義了一個(gè)類叫Filedtype,為了節(jié)省空間,我只用了一個(gè)char來存儲文件類型,按照從低位到高位的順序,使用位操作來設(shè)置和獲取信息,我定義第一位代表可讀,第二位代表可寫,第三位代表可執(zhí)行,通過與&操作來獲取信息,通過或|操作來設(shè)置信息。對于創(chuàng)建時(shí)間來說,我認(rèn)為給文件頭allocate的時(shí)候算創(chuàng)建,于是我在allocate開始的地方加上createTime=stats->totalTicks,而對于lastModifyTime來說,我選擇在writeback的里面寫入類似的賦值語句,而lastReferTime則是在FetchFrom里面,后來在調(diào)試的時(shí)候發(fā)現(xiàn)如果創(chuàng)建之后就沒有再讀過,那么lastReferTime就會是0,這樣不符合實(shí)際,所以我在allocate里面給三個(gè)時(shí)間都賦了值。但是定義了這些屬性之后還需要調(diào)整文件頭中的dataSectors的大小,因?yàn)槊總€(gè)文件頭都只占了一個(gè)sector,增加了額外的信息之后就會減少一個(gè)文件所能使用的塊數(shù)。對于路徑來說,這個(gè)比較麻煩,實(shí)際上是我在完成了exercise3以后才回來完成的,我在文件頭里面加入一個(gè)信息是父目錄的文件頭的塊號,但是因?yàn)槲募^里面并沒有存儲改文件的名字,名字在上級目錄中,所以我向上找兩級父目錄,在這個(gè)祖父目錄中通過父目錄的塊號來找到父目錄的文件名(如果中間遇到了parentDire是-1的話,說明遇到了root,停止向上查找),為了實(shí)現(xiàn)這個(gè)功能,我在directory中加入了一個(gè)findName函數(shù),這個(gè)函數(shù)通過匹配sector號來找到文件名。在實(shí)現(xiàn)了多級目錄之后,只要調(diào)用-l就可以打印出所有我定義在文件頭中的信息,以及文件的父目錄。Exercise3:這個(gè)練習(xí)要求通過使用間接索引來使得文件的大小突破4K,主要思路并不難想象,定義一個(gè)一級索引作為例子,在文件頭中使用一個(gè)int型屬性來指示一級索引所在的文件塊,然后如果文件小于直接索引所能提供的大小,那么把這個(gè)間接索引值賦成無效的-1,否則在bitmap中找一個(gè)空閑塊,賦給這個(gè)間接索引值,然后通過synchdisk的writesector把寫回這個(gè)塊即可。想明白以后,最大的困難是不知道文件是怎么寫的,因?yàn)橹翱吹竭^許多各種各樣的writeback,有的是用塊號,有的是用openfile。參考文件頭自己的writeback方法,它用的是synchdisk的writesector,這個(gè)函數(shù)接受一個(gè)塊號作為地址,但是開始的時(shí)候我不明白的是為什么第二個(gè)參數(shù),也就是寫的內(nèi)容是(char*)this,比較奇怪,后來想了很久明白了這里就是把這個(gè)對象的內(nèi)容整體寫到塊中,而這個(gè)對象的內(nèi)容就是類中的屬性。也就是說我可以把任何我想寫的東西寫入磁盤塊中,只要大小不超過一個(gè)塊的大小,而且必須包裝成char*數(shù)組的形式,于是我定義一個(gè)int型數(shù)組來存放文件頭中需要的磁盤塊號,在分配或者修改的時(shí)候把這個(gè)數(shù)組寫回磁盤即可。在分配函數(shù)allocate中,我首先判斷需要的大小是不是超過直接索引能夠存儲的范圍,如果沒有的話,皆大歡喜,直接使用原來的代碼,否則,先給直接索引分配需要的磁盤塊,之后給間接索引分配一個(gè)塊,并且存儲到間接索引這個(gè)屬性中,然后創(chuàng)建一個(gè)前面所說的數(shù)組,大小就是Sectorsize/sizeof(int),這樣,給需要的塊找到相應(yīng)的位置,其余的賦成-1,最后把這個(gè)數(shù)組寫到找到的間接索引指向的塊,大功告成。測試的時(shí)候,我先用python制造了一個(gè)超過4K大小的文件叫huge,之后使用nachos-cp把這個(gè)文件復(fù)制到nachos中再-D顯示內(nèi)容,結(jié)果成功了,說明間接索引能夠很好的工作。Exercise4:多級目錄主要和directory有關(guān),但是在實(shí)際實(shí)現(xiàn)的時(shí)候發(fā)現(xiàn)directory的功能實(shí)在是太弱了,僅靠directory無法實(shí)現(xiàn)多級目錄,directory里面實(shí)際上與多級目錄相關(guān)的是add這個(gè)函數(shù),但是這個(gè)函數(shù)實(shí)際上也只是將文件名和sector號的這樣一個(gè)對加入到directory對象的table屬性中(如果沒有重名的時(shí)候),而真正的創(chuàng)建目錄等操作這里無法完成,也就是說得在其它地方創(chuàng)建好目錄,甚至寫到相應(yīng)的磁盤塊之后,這時(shí)向directory中加入這一項(xiàng)才有意義。而且向directory中加入的只應(yīng)該是對應(yīng)文件頭的塊號(這一點(diǎn)我開始的時(shí)候沒有按照這樣實(shí)現(xiàn),結(jié)果到了后來出現(xiàn)了很多矛盾)。因?yàn)槟夸浀膄etchfrom和writeback針對的都是openfile,這個(gè)openfile需要的是文件頭,也就是說directory里的fetchfrom需要通過目錄文件頭的塊號來打開目錄。所以如果自己需要建目錄的話,不僅需要寫目錄所在的塊,還要創(chuàng)建并寫入目錄對應(yīng)的文件頭所在的塊。再看每個(gè)目錄項(xiàng)中存儲的內(nèi)容,最開始的時(shí)候是inUse和文件名-塊號對,為了區(qū)別目錄中的目錄項(xiàng)是文件還是目錄,還需要加入是否是目錄這個(gè)屬性,為了節(jié)省空間,我同樣使用位運(yùn)算來標(biāo)記inUse和isDire兩個(gè)狀態(tài),即提供了get和set方法。之后我想仿照創(chuàng)建文件并加入目錄的方法,來創(chuàng)建目錄并加入目錄,首先來實(shí)驗(yàn)只加到根目錄中,我的做法是修改filesys中的create,要求create的參數(shù)中包括要創(chuàng)建的是不是目錄。做法基本上照抄創(chuàng)建文件的方法,不同的是allocate的時(shí)候需要的大小是DirectoryFileSize(有宏定義好的),并且不僅要寫回根目錄、bitmap和文件頭,還需要寫回新創(chuàng)建的目錄。實(shí)驗(yàn)的時(shí)候創(chuàng)建一個(gè)目錄dire,并且list出來,能夠顯示,但是當(dāng)然是空的。接下來就是考慮如何真正實(shí)現(xiàn)多級目錄,也就是說怎么在我新創(chuàng)建的目錄下創(chuàng)建目錄或者添加文件呢,我想到了正在使用的linux在文件頭中有.和..兩個(gè)文件,..代表的是上一級目錄(前面已經(jīng)介紹了實(shí)現(xiàn)),那么就是說還需要支持.文件,也就是當(dāng)前工作目錄。怎么辦呢?我在filesys中添加了workingDireFile這個(gè)openfile*類型的屬性(因?yàn)閎itmap和根目錄也是通過這個(gè)屬性存儲的)。在filesys初始化的時(shí)候把創(chuàng)建出來之后的根目錄賦給工作目錄(符合常理),在create的時(shí)候首先判斷工作目錄是不是Null,如果是的話,那么把根目錄賦給工作目錄,之后接下來的一切之前和根目錄有關(guān)的操作,都改成使用工作目錄。在open和remove中也同樣如此。有了這些還不夠,我們還需要支持改變工作目錄,否則就不可能在新的目錄下創(chuàng)建文件或者目錄,于是我定義了一個(gè)gotoDirectory的函數(shù),接受名字(目錄或文件)作為參數(shù),這個(gè)函數(shù)首先打開工作目錄,在工作目錄下找是否有具有這個(gè)名字的目錄,如果有這個(gè)目錄的話,那么把這個(gè)目錄作為工作目錄。這樣工作就基本完成了??墒菧y試的時(shí)候要看到結(jié)果,于是我修改了print函數(shù)(主要是directory中的),這里主要就是判斷是否是目錄,如果不是目錄,那么依舊使用原來的print,如果是目錄的話,那么先打開這個(gè)目錄,之后執(zhí)行目錄的print,這樣即使有多層的目錄也可以遞歸地打印出結(jié)果了,list的修改方式類似,也需要遞歸,不過在文件頭層面上需要打印出文件中我自己定義的信息和父目錄名,方法上面已經(jīng)說過了。Exercise5:動態(tài)調(diào)整文件大小在這個(gè)任務(wù)中,我主要做了將文件擴(kuò)大的操作,也就是說如果當(dāng)前文件的大小不夠需要寫入的內(nèi)容的大小,那么我就根據(jù)另外需要的磁盤塊的數(shù)量,給這個(gè)文件分配更多的磁盤塊。為了實(shí)現(xiàn)這個(gè)功能,我在filehdr中定義了一個(gè)函數(shù)叫做AllocateMore,這個(gè)函數(shù)接受兩個(gè)參數(shù),一個(gè)是另外需要的文件塊數(shù),另一個(gè)是實(shí)際需要的字節(jié)數(shù)。在這個(gè)函數(shù)的實(shí)現(xiàn)過程中,我主要參考了allocate和create兩個(gè)函數(shù),要得到更多的空間,首先需要先得到標(biāo)記磁盤空閑位置的bitmap,因?yàn)閒ilesys里面有這個(gè)屬性,所以直接讀出freeMapFile這個(gè)屬性并且通過它取出bitmap,然后判斷直接索引中是不是還有剩余空間,之后判斷直接索引是不是足夠提供需要的磁盤塊,如果是的話,那么把需要的磁盤塊分配給這個(gè)文件,增加文件頭中的磁盤塊數(shù)到實(shí)際塊數(shù),寫回bitmap,并且返回True。之后如果直接索引不足以提供需要的磁盤塊數(shù),那么先把直接索引中剩余的塊分配出去,之后再將間接索引中的塊分配出去,直到滿足需求為止。其中,如果本身沒有間接索引的話,還需要首先給這個(gè)間接索引分配一個(gè)塊,最后的時(shí)候還要把這些都寫回到磁盤中。第二部分:系統(tǒng)調(diào)用Exercise6:Syscall.hStart.sException.cc這兩個(gè)文件需要一起結(jié)合著看,syscall這個(gè)頭文件可以說沒有沒有相對應(yīng)的.cc文件,它對應(yīng)的實(shí)際上是start.s文件,就我們關(guān)心的幾個(gè)函數(shù)來說,create,open,close,read,write這幾個(gè)函數(shù)都是在syscall里面定義了函數(shù)的signature,而在start.s中把這些函數(shù)對應(yīng)的系統(tǒng)調(diào)用號SC_...放入二號寄存器中,使得exception里面的exceptionhandler可以識別出對應(yīng)的系統(tǒng)調(diào)用類型,來進(jìn)行相應(yīng)的處理。由于系統(tǒng)調(diào)用不能通過傳統(tǒng)的方式傳遞參數(shù),在start里面的注釋中可以看出,4~7號寄存器可以用來傳遞參數(shù),而2號寄存器在exception里面應(yīng)該作為傳遞返回值的寄存器。由于exception在用戶線程部分就已經(jīng)用過多次,這里就不介紹了。Exercise7,8:系統(tǒng)調(diào)用和調(diào)試就像之前實(shí)現(xiàn)tlbmiss和pagefault的時(shí)候一樣,這次也是主要修改exception中的exceptionhandler,其實(shí)有了前面的基礎(chǔ),這個(gè)練習(xí)相對簡單,但是最麻煩的是傳遞參數(shù)的問題,雖然知道是通過4個(gè)寄存器來傳遞參數(shù),但是實(shí)際編寫的時(shí)候發(fā)現(xiàn)并不是這個(gè)簡單,比如create需要的參數(shù)是一個(gè)char*指針,指向的是一個(gè)字符串,這個(gè)字符串是要創(chuàng)建的文件的名字,開始的時(shí)候我直接把從4號寄存器中讀出的int值強(qiáng)制轉(zhuǎn)化為char*直接輸出,發(fā)現(xiàn)出現(xiàn)了段錯誤,其它任何提示都沒有,直接就頭大了,后來經(jīng)過同學(xué)提醒,想起了這里的內(nèi)存空間應(yīng)該是一致的內(nèi)存空間而不是宿主機(jī)的內(nèi)存空間,如果直接使用char*轉(zhuǎn)化過的那個(gè)int型地址,得到的其實(shí)是宿主機(jī)上的相應(yīng)地址而不是nachos的內(nèi)存地址。這樣就是說我們應(yīng)該去machine->mainMemory里面找這個(gè)字符串,有用的還是得到的那個(gè)地址,但是麻煩的是readMemory這個(gè)函數(shù)只接受int*作為寫入的地址,也就是說如果想直接向我自己定義的char數(shù)組中一個(gè)一個(gè)地寫入char,是不可以的,因?yàn)檫@樣會覆蓋掉相鄰位置的字節(jié)。于是只能模擬讀int的方式,一次讀入4個(gè)字節(jié),每次把地址加4(而不是1)。這樣操作之后終于可以正確地輸出這個(gè)名字參數(shù)了。接著把名字和文件大?。ㄎ夷J(rèn)為一個(gè)sector的大小)作為參數(shù)傳遞給filesys的create,就可以創(chuàng)建文件了。但是開始寫的時(shí)候改正完這個(gè)錯誤還不算完,程序運(yùn)行的時(shí)候就像死循環(huán)一樣,不停地在create里面轉(zhuǎn),后來想到之前寫的tlbmiss的部分,明白了這里也應(yīng)該改pc指針的值,把nextpc的值賦給pc寄存器,這樣之后create終于可以很好地運(yùn)行了。完成了一個(gè)系統(tǒng)調(diào)用,其它的其實(shí)就簡單多了,大多數(shù)是函數(shù)的包裝。對于open來說,還需要在當(dāng)前線程的地址空間中增加把這個(gè)打開文件號的功能,我在地址空間中定義了一個(gè)存放打開文件的數(shù)組,每次找空的位置放入新的打開文件。這樣open就基本完成了,close就是delete數(shù)組中這個(gè)文件號對應(yīng)的文件,然后把數(shù)組中這個(gè)位置置為null即可。對于write和read來說,需要有讀文件寫入buffer的操作或者從buffer里面讀然后寫入到文件,因?yàn)閛penfile的read和write都是根據(jù)seekposition的位置讀寫的,具有不確定性,于是我選擇了使用readat和writeat,和讀文件名的時(shí)候不同的是,這里buffer和mainMemory都是char類型的,所以在寫buffer的時(shí)候可以一個(gè)字節(jié)一個(gè)字節(jié)地寫。而在寫文件的時(shí)候還需要判斷當(dāng)前文件的大小是不是足夠盛放這些要寫的內(nèi)容,如果不夠的話,那么還需要先allocatemore。測試程序的話,很簡單,就是仿照halt.c的寫法,先create,然后open,write,read,close最后halt就可以了。這里我碰到的一個(gè)問題是不能在main里面定義變量(所謂的局部變量),必須在main外面定義全局變量,否則編譯不會通過。Exercise9:閱讀代碼:Synchdisk.hsynchdisk.ccSynchdick的主要作用是確保磁盤訪問的互斥性,為了做到這一點(diǎn),它是用了信號量Semaphore和互斥鎖lock,lock的作用是起到比較“霸道”的讀寫鎖的作用,也就是說,在同一時(shí)刻,只能有一個(gè)線程在讀或者寫,而不是想真正的讀寫鎖那樣只排斥讀的時(shí)候的寫操作,或者寫的時(shí)候的讀操作。而Semaphore是用來起到類似于中斷的作用,當(dāng)發(fā)起讀或者寫操作以后,就使信號量進(jìn)行P操作,而當(dāng)磁盤的讀或者寫操作結(jié)束后,就會進(jìn)行V操作,喚醒synchdisk,繼續(xù)執(zhí)行剛才的操作。而這個(gè)V操作其實(shí)是通過synchdisk的包裝函數(shù)RequestDone函數(shù)來實(shí)現(xiàn)的,這個(gè)包裝函數(shù)的作用在于disk操作結(jié)束之后就會自動調(diào)用作為參數(shù)傳入disk的構(gòu)造函數(shù),這樣disk在進(jìn)行完讀寫操作后就可以自動調(diào)用這個(gè)函數(shù),從而間接進(jìn)行V操作。而V操作執(zhí)行完畢之后,就會解鎖。實(shí)現(xiàn)SynchConsole其實(shí)在通過看progtest里面有關(guān)console的實(shí)現(xiàn)就可以看出,nachos的console也是可以互斥訪問的,但是當(dāng)前是通過在外部包上PV操作來實(shí)現(xiàn)的,在ConsoleTest中,創(chuàng)建了兩個(gè)信號量,一個(gè)是readAvail,一個(gè)是WriteDone,在取字操作之前,首先readAvail進(jìn)行P操作,把這個(gè)字符反過來輸出到屏幕上之后,WriteDone進(jìn)行P操作,這樣,就可以仿照這樣的方式,創(chuàng)建一個(gè)新的類SynchConsole,像SynchDisk一樣對Console進(jìn)行包裝,從而實(shí)現(xiàn)目標(biāo)。為了避免編譯的麻煩,我選擇在console中直接定義SynchConsole類,而不另外使用其它文件。仿照SynchDisk,我在SynchConsole中使用了讀鎖readLock,寫鎖writeLock,因?yàn)閏onsole中使用了readAvail和writeDone兩個(gè)信號量,而Console會在讀寫控制臺之后調(diào)用兩個(gè)信號量的V操作,所以我在SynchConsole中,也定義了兩個(gè)包裝函數(shù)也叫readAvail和writeDone,這兩個(gè)函數(shù)也像progtest里面的同名函數(shù)一樣,直接調(diào)用synchConsole中的對應(yīng)的V操作。于是,在構(gòu)造函數(shù)中,new出讀寫鎖,讀寫信號量,以及真正進(jìn)行控制臺操作的console成員變量,在putchar中首先取得寫鎖,然后調(diào)用console的putchar函數(shù),之后調(diào)用寫信號量的P操作,最后釋放寫鎖,getchar的操作與此類似,只是要先調(diào)用讀的信號量的P操作,然后調(diào)用console的getchar函數(shù)。這樣之后,synchConsole就完成了。Exercise10:為了保證第一個(gè)要求,每一個(gè)線程擁有獨(dú)自的文件訪問位置,我在Addrspace中定義了一個(gè)OpenFile指針數(shù)組,為了簡便,我直接通過宏指定這個(gè)數(shù)組的大小為10,因?yàn)檫@里只是限制用戶打開的文件之間互不干擾,于是我在處理系統(tǒng)調(diào)用Open的時(shí)候(exceptionhandler里面),把要打開的OpenFile指針放到currentThread的space里面,為了保持ExceptionHandler代碼的簡潔,我在addrspace里面定義了一個(gè)AddToOpenFile函數(shù),用來通過遍歷數(shù)組找到空位,把OpenFile的指針放入到space的openFiles數(shù)組(我自己定義的)中。這個(gè)函數(shù)會返回在數(shù)組中的下標(biāo),這樣就可以把這個(gè)文件號作為返回值了。相應(yīng)的,還需要在Close里面加上從數(shù)組中去除要關(guān)閉的OpenFile,于是我把數(shù)組中的指針delete掉,并且置為NULL。之后在Read和Write中也就可以通過文件下標(biāo)直接得到space中的OpenFile了。對于第二個(gè)要求,我認(rèn)為既然已經(jīng)使用了SynchDisk,那么就是原子化的了,因?yàn)樵谧x寫之前都必須首先申請鎖。對于第三個(gè)要求,為了保證在要刪除一個(gè)文件時(shí)必須保證其它線程已經(jīng)關(guān)閉這個(gè)文件,我在system.cc中定義了一個(gè)全局的打開文件鏈表,鏈表中存放文件打開的次數(shù)和文件頭所在的sector號,并且實(shí)現(xiàn)了AddOpenFile和RemoveOpenFile兩個(gè)函數(shù),AddOpenFile在鏈表中查找是否已經(jīng)打開了這個(gè)文件(通過打開文件所在的sector號是否相同來判斷),如果已經(jīng)打開了這個(gè)文件,那么打開次數(shù)加一,否則把這一項(xiàng)加入到鏈表中,打開次數(shù)設(shè)置為1。RemoveOpenFile也是先找這個(gè)文件,如果找到則給引用次數(shù)減一,如果沒找到,返回-1。為了在刪除判斷的時(shí)候方便,我還定義了GetOpenFileNum這個(gè)函數(shù),這個(gè)函數(shù)通過和上面一樣的方法,遍歷找到這個(gè)文件的打開次數(shù),在FileSys得到Remove里面,如果查詢到要刪除的打開文件次數(shù)是0,那么刪除這個(gè)文件,否則返回False。這樣就完成了這個(gè)Exercise。Challenge1:為了實(shí)現(xiàn)Exec系統(tǒng)調(diào)用,可以仿照progtest里面的StartProcess,于是我基本上按照StartProcess的實(shí)現(xiàn)方法在Exception.cc里面加入一個(gè)同名函數(shù)StartProcess,不同的只是在于這里我需要從寄存器和machine的mainMemory里面讀取出可執(zhí)行文件名,因?yàn)樾枰С侄嗑€程執(zhí)行不同的程序,所以我在ExceptionHandler里面的SC_Exec里面還需要使用新創(chuàng)建的thread,并且用這個(gè)新的thread去Fork出StartProcess這個(gè)函數(shù),這樣,即使多次使用系統(tǒng)調(diào)用Exec,也可以并行地執(zhí)行了。對于Join來說,主要是需要被Join的線程等待join的線程,可以通過在調(diào)度到父線程時(shí)不斷地yield來實(shí)現(xiàn)。為了明確什么要等待的子線程是不是已經(jīng)結(jié)束運(yùn)行了,需要在父線程中維護(hù)一個(gè)數(shù)組來記錄該線程都有哪些子線程,這樣也就給了join目標(biāo)參數(shù),我在thread類中定義了這樣一個(gè)數(shù)組,并且定義了相應(yīng)的將子線程加入到數(shù)組中的函數(shù)AddChild,這個(gè)函數(shù)遍歷數(shù)組,找到空位后將子線程指針加入到空位中,返回剛才加入的數(shù)組下標(biāo)。并且需要在thread類中加入join函數(shù),這個(gè)函數(shù)接收子線程號作為參數(shù),如果數(shù)組中這個(gè)下標(biāo)的線程還不是NULL(通過while循環(huán)來判斷),那么就一直Yield。這樣的機(jī)制必須允許子線程到父線程中修改子線程數(shù)組,于是我在AddChild函數(shù)里面,把currentThread賦給子線程的parentThread指針,并且在thread的finish函數(shù)里面把父線程的具有子線程spaceId(在exec系統(tǒng)調(diào)用中賦給子線程)的數(shù)組元素賦成NULL,這樣當(dāng)父線程再次檢查的時(shí)候就可以跳出while循環(huán)了。對于Exit,比較簡單直接調(diào)用currentThread的finish函數(shù)并且使得pc指針前進(jìn)即可。Challenge4:實(shí)現(xiàn)Fork和Yield從syscall.h中可以看出,在Nachos中Fork和Exec的區(qū)別在于Exec會創(chuàng)建不同的Addrspace而Fork和父線程使用相同的Addrspace,Nachos和Linux的Fork的不同點(diǎn)在于Linux只需要復(fù)制父線程的空間即可,而Nachos直接要求Fork出來的線程運(yùn)行一個(gè)函數(shù)。于是在ExceptionHandler中我加入對SC_Fork的支持,首先我new出一個(gè)thread,并把它加入到currentThread的子線程中,接下來問題來了,怎么使得子線程和父
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 香椿種植轉(zhuǎn)讓合同范本
- 南昌購房合同范本
- 余泥外運(yùn)合同范本
- 衛(wèi)星定位合同范本
- 合同范本從里
- 不良資產(chǎn)合同范本
- 小型裝修合同范本
- 北京地暖合同范本
- 包工頭和工人簽合同范本
- 合同范本快速打字
- 消防工程常用設(shè)施三維圖解
- 慢性乙型肝炎防治指南(2022年版)解讀
- 搟筋課件教學(xué)課件
- 醫(yī)院工程改造工程施工組織設(shè)計(jì)方案
- 英語人稱代詞和物主代詞練習(xí)題(附答案)
- 計(jì)算機(jī)一級考試WPS試題及答案
- 生豬屠宰獸醫(yī)衛(wèi)生檢驗(yàn)人員理論考試題庫及答案
- 《Windows server操作系統(tǒng)》Windows Server 2019全套教學(xué)課件
- 全科醫(yī)生題庫附有答案
- 2024年12月大學(xué)英語四級CET-4真題試卷
- 煤礦應(yīng)急叫應(yīng)、回應(yīng)、響應(yīng)機(jī)制
評論
0/150
提交評論