操作系统课设实验五---Nachos文件系统扩展
這次的實驗讓我想起了上學期被操作系統的九個實驗支配的恐懼,因為這次可能也是前五次試驗中最難的一次了,讀源碼加實現花了可能一兩天的時間,所以也有必要記錄一下,有些地方做的不是很好,比如Makefile自己寫的話可能不需要把所有文件都從filesys復制到lab5,可是我太菜做不到,所以先這樣湊合著吧emmm,畢竟還有一堆其他實驗。
一、實驗要求重述
目標
在lab5目錄下,通過對nachos源代碼的修改,實現可擴展的文件系統,即滿足以下需求
- 當一個文件創建的時候,它的初始大小為0
- 文件的大小可以在文件內容增加時改變
如:100 bytes大小的文件在50 bytes的位置往后再寫100個byte,文件大小變為150 bytes.
設計與實現的提示
取消最后兩行的注釋即可。此外,在取消注釋之后還需要在OpenFile的類中實現Writeback方法。
二、分析
首先我們需要分析nachos文件部分的源代碼,一方面是要了解那七個文件的用法,另一方面要閱讀測試使用的main. cc和fstest. cc,通過閱讀源碼,我們才能達到盡可能少的修改源碼來實現功能的目的。
通過對這些源碼的閱讀以及實驗指導書的提示,首先我們需要修改OpenFile這個類,要實現它的WriteBack方法,這個方法的作用是將大小改變的文件頭信息寫回磁盤。其次在寫的方法上我們也要進行修改,那就是該類的WriteAt方法,而因為這里的邏輯是假設文件大小固定,因此我們需要為它添加一個申請新的磁盤空間的方法,這里我在OpenFile類新建了一個AllocateSpace方法。但在實際申請磁盤空間的時候,應該需要在FileHeader類中進行,因此我們為其增加一個ExtendSpace方法。最后,在文件大小變化的時候,應該修改FileHeader類中的numBytes的值,因此我們需要添加一個set方法SetLength。這一切就緒之后,就可以依次實現這些方法了。
ps:原來我在AllocateSpace方法中是直接先釋放所有磁盤空間再申請新空間來實現擴容的,經過小伙伴指正我也發現這樣確實不行,如果內容存儲扇區之前的扇區空間都被別的內容占用的話的沒有問題,可是如果有空扇區的話,申請之后文件頭信息中指向的內容扇區就會和實際存儲的扇區有偏差。
至少之前的設計是有問題的,可以用以下命令實驗下試試
之前的結果:
現在的結果
三、實現
首先來說FileHeader類中的SetLength方法,我們只需要簡單的設置即可,因此它的代碼也非常簡單,如下:
void FileHeader::SetLength(int length) {this->numBytes=length; }下一步來實現相對簡單一點的OpenFile類中的WriteBack方法,這里我們要把其內部的FileHeader類型的成員hdr寫回到磁盤中,FileHeader內部實現了寫回磁盤的方法,但是它需要扇區參數,而在這個OpenFile類中這個值并不好取得,因此我們再給OpenFile類增加一個私有成員sector,并在其構造函數中利用傳入的頭信息扇區號來初始化。如下:
OpenFile::OpenFile(int sector) { hdr = new FileHeader;hdr->FetchFrom(sector);seekPosition = 0;this->sector=sector; }這樣,我們就能在WriteBack方法中拿到扇區號了。如下:
void OpenFile::WriteBack() {hdr->WriteBack(sector); }然后,我們就只剩下OpenFile類中的AllocateSpace與WriteAt函數和FileHeader類中的ExtendSpace函數需要完成了。
由于OpenFile類里面的兩個函數的實現都需要使用到ExtendSpace函數的功能,因此這里首先來實現這個函數,這個函數模仿Allocate函數實現,需要做的就是根據要申請的空間大小和比特圖來申請新的磁盤扇區空間。如下:
bool FileHeader::ExtendSpace(BitMap *freeMap,int appendSize) {int oriSectors=numSectors; //記錄原空間大小numSectors = divRoundUp(appendSize, SectorSize)+oriSectors; //計算新扇區大小 // printf("newSectorsNum is %d\n", numSectors);if (freeMap->NumClear() < numSectors-oriSectors){numSectors=oriSectors;//將空間大小復原return FALSE; // not enough space}for (int i = oriSectors; i < numSectors; i++) //申請新的扇區dataSectors[i] = freeMap->Find();return TRUE; }在WriteAt函數中需要調用AllocateSpace函數,所以首先應該來實現AllocateSpace函數:
這個函數的功能應該是給它一個需要擴展的文件長度,它就能申請到這個長度對應的扇區來進行以后的存儲,而具體的申請操作在OpenFile類的FileHeader類型的hdr成員已經實現了,這里可以直接調用它來做:
完成這些之后,可以來實現WriteAt方法了,這個方法在實現的時候已經考慮到了不從頭開始寫的情況,因此我們也不需要太擔心ap和hap命令的實現,在實現這個函數之前,我們應該先進行一些思考:
如果是cp模式,即直接復制UNIX文件的內容到nachos文件系統中去,則當前的代碼已經不需要修改了。如果我們要實現ap或者hap模式,則需要申請新的空間,而剩余的部分也不需要進行修改,因此,我們首先需要判斷一下是不是追加模式,如果是,則去申請新的空間。而判斷是否為追加模式,我們可以用當前文件指針的位置是否大于文件大小來確定。如果是追加模式,我們則分兩種情況討論:
1.加上新的字符后的文件大小還沒有占滿整個扇區,這時只需要設置文件大小即可。
2.加上新的字符后文件大小已經超過了整個扇區,這時候就需要申請新的磁盤空間來對文件進行存儲了。
此外再排除一些WriteAt本來的關于文件長度的一些限制之后,修改的WriteAt方法如下:
int OpenFile::WriteAt(char *from, int numBytes, int position) {int fileLength = hdr->FileLength();int i, firstSector, lastSector, numSectors;bool firstAligned, lastAligned;char *buf; // printf("seekPosition is %d,fileLength is %d\n",seekPosition,fileLength);if (numBytes < 0) return 0; // check requestif(seekPosition>=fileLength) //如果文件指針已經超過了文件大小{numSectors=divRoundUp(fileLength,SectorSize); //計算當前需要的扇區int numPos=seekPosition+numBytes; //計算添加新字節之后的指針位置if(numPos>numSectors*SectorSize) //如果文件為空或者超過了已有扇區空間{AllocateSpace(numPos-numSectors*SectorSize);//申請新空間fileLength+=numBytes; //增大文件空間}hdr->SetLength(numPos); //根據新指針位置設置新的文件大小}//寫入的部分已經考慮了從中間寫入的情況if(fileLength==0) return 0;DEBUG('f', "Writing %d bytes at %d, from file of length %d.\n", numBytes, position, fileLength);firstSector = divRoundDown(position, SectorSize);lastSector = divRoundDown(position + numBytes - 1, SectorSize);numSectors = 1 + lastSector - firstSector; // printf("firstSector is %d,lastSector is %d\n",firstSector,lastSector);buf = new char[numSectors * SectorSize];firstAligned = (bool)(position == (firstSector * SectorSize));lastAligned = (bool)((position + numBytes) == ((lastSector + 1) * SectorSize));// read in first and last sector, if they are to be partially modifiedif (!firstAligned)ReadAt(buf, SectorSize, firstSector * SectorSize); if (!lastAligned && ((firstSector != lastSector) || firstAligned))ReadAt(&buf[(lastSector - firstSector) * SectorSize], SectorSize, lastSector * SectorSize); // copy in the bytes we want to change bcopy(from, &buf[position - (firstSector * SectorSize)], numBytes);// write modified sectors backfor (i = firstSector; i <= lastSector; i++) synchDisk->WriteSector(hdr->ByteToSector(i * SectorSize), &buf[(i - firstSector) * SectorSize]);delete [] buf;return numBytes; }最后,我們則是按照實驗指導書上的提示,在fstest.cc文件中取消掉調用WriteBack的部分的注釋。
// Write the inode back to the disk, because we have changed itopenFile->WriteBack();printf("inodes have been written back\n");源碼部分處理完成以后就要進行編譯與測試了,這里實驗要求自己編寫Makefile文件,由于nachos的編譯模塊過于復雜,這里我先把filesys中的所有除fstest.cc之外的文件復制到lab5目錄下,然后修改Makefile文件來實現的編譯,兩個相關的Makefile代碼如下:
Makefile.local:
ifndef MAKEFILE_LAB5_LOCAL define MAKEFILE_LAB5_LOCAL yes endef# Add new sourcefiles here.CCFILES +=bitmap.cc\directory.cc\filehdr.cc\filesys.cc\fstest.cc\openfile.cc\synchdisk.cc\disk.cc\main.ccifdef MAKEFILE_USERPROG_LOCAL DEFINES := $(DEFINES:FILESYS_STUB=FILESYS) else INCPATH += -I../userprog -I../lab5 DEFINES += -DFILESYS_NEEDED -DFILESYS endifendif # MAKEFILE_FILESYS_LOCALMakefile:
ifndef MAKEFILE_LAB5 define MAKEFILE_LAB5 yes endef# You can re-order the assignments. If filesys comes before userprog, # just re-order and comment the includes below as appropriate.include ../threads/Makefile.local include ../lab5/Makefile.local #include ../userprog/Makefile.local #include ../vm/Makefile.local #include ../filesys/Makefile.localinclude ../Makefile.dep include ../Makefile.commonendif # MAKEFILE_FILESYS這里有一個源碼中的坑,就是在測試要用的main.cc中,如果不改的話編譯會報如下錯誤:
只需要進入lab5下的main. cc,把NAppend函數的聲明修改一下即可:
四、測試
測試可能需要若干命令,這里我們可以寫一個Shell腳本來保存連續的命令,需要的時候調用然后觀察最后結果即可,這里我準備了兩個測試腳本,修改完源碼并且編譯之后執行即可:
測試ap參數:
rm DISK ./nachos -f ./nachos -cp test/small small ./nachos -ap test/small small ./nachos -cp test/empty empty ./nachos -ap test/medium empty ./nachos -D測試hap參數:
rm DISK ./nachos -f ./nachos -cp test/small small ./nachos -cp test/big big ./nachos -hap test/big small ./nachos -hap test/small big ./nachos -D將上述兩個腳本分別另存為ap. sh和hap. sh,然后在命令行中執行如下命令給予其執行權限:
$chmod a+x ap.sh $chmod a+x hap.sh然后首先我們測試ap參數的運行情況,運行結果如下:
可見,與實驗指導書預計的結果一致,即ap功能得以實現。
接下來再來測試一下hap命令。
這里測試了兩種情況,即從大文件的中間寫小文件和從小文件的中間寫大文件。結果如下:運行結果如下:
從結果來看,hap的功能也得到了實現。
五、結論分析與體會
從輸出結果來看,拓展之后的文件系統在保證了基本的cp命令執行不出錯的情況下,增加了ap和hap兩個命令,讓原來固定大小的文件系統變成了大小可變的文件系統。
本次實驗在掌握了nachos基本文件命令用法的情況下,對其功能進行了拓展,增加了文件可變的功能,而實現這個功能的前提也是足夠了解nachos磁盤系統相關的源代碼,因此通過擴展這個功能,我對nachos文件系統相關的部分有了更深的認識,也對操作系統中所講的文件系統相關的內容進行了很好的回顧。
總結
以上是生活随笔為你收集整理的操作系统课设实验五---Nachos文件系统扩展的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3、Finished with erro
- 下一篇: SNS大负载系统解决方案研究