基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)_第1頁
基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)_第2頁
基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)_第3頁
基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)_第4頁
基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)_第5頁
已閱讀5頁,還剩106頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)DesignandImplementationofFileSystemBasedOnBochsVirtualMachine摘要隨著科技不斷的進(jìn)步,我們?nèi)粘P枰幚淼奈募苍絹碓酱螅@個時候就凸顯了文件系統(tǒng)的重要性。在操作系統(tǒng)中,文件系統(tǒng)的主要目的是實現(xiàn)對文件的按名存取。如果一個硬盤上沒有一個良好的文件系統(tǒng),這將是一個難以想象的結(jié)果。因為硬盤是一個低速設(shè)備,而CPU和內(nèi)存都是高速設(shè)備,這就需要操作系統(tǒng)中的文件系統(tǒng)對文件進(jìn)行良好的組織,實現(xiàn)對文件的正確操作。在硬盤中,其讀寫單位是扇區(qū),操作系統(tǒng)往往會等到數(shù)據(jù)積攢到一定的數(shù)量才會進(jìn)行訪問硬盤,這些數(shù)據(jù)就是塊,一個塊由多個扇區(qū)組成,塊大小是扇區(qū)大小的整數(shù)倍。本文件系統(tǒng)采用索引結(jié)構(gòu)——inode,參照Linux系統(tǒng)中的ext2文件系統(tǒng),它將文件以索引結(jié)構(gòu)來組織,避免了訪問某一數(shù)據(jù)塊需要從頭把其前所有數(shù)據(jù)塊再遍歷一次的缺點。在開發(fā)文件系統(tǒng)實現(xiàn)了硬盤驅(qū)動程序,基于之前寫好的系統(tǒng)內(nèi)核,本文件系統(tǒng)用C語言開發(fā),編譯環(huán)境為gcc,然后再bochs虛擬機(jī)上對代碼進(jìn)行調(diào)試實現(xiàn)。最終能夠?qū)崿F(xiàn)創(chuàng)建文件、文件的打開與關(guān)閉、實現(xiàn)文件寫入、讀取文件、實現(xiàn)文件刪除功能、創(chuàng)建目錄、遍歷目錄、刪除目錄、任務(wù)的工作目錄、獲得文件屬性等一些文件系統(tǒng)中的必要功能。關(guān)鍵詞文件系統(tǒng)、inode、C語言、gcc、bochs虛擬機(jī)AbstractWiththecontinuousadvancementoftechnology,thefilesweneedtohandledailyaregettingbiggerandbigger.Thistimehighlightstheimportanceofthefilesystem.Intheoperatingsystem,themainpurposeofthefilesystemistoachievename-basedaccesstofiles.Ifaharddiskdoesnothaveagoodfilesystem,thiswillbeanunimaginableresult.Becausetheharddiskisalow-speeddevice,andboththeCPUandthememoryarehigh-speeddevices,thisrequiresthefilesystemintheoperatingsystemtoorganizethefileswellandachievecorrectoperationofthefiles.Intheharddisk,thereadandwriteunitsaresectors.Theoperatingsystemwillwaituntilthedataisaccumulatedtoacertainamountbeforeaccessingtheharddisk.Thedataisablock.Ablockconsistsofmultiplesectors.Theblocksizeisthesizeofthesector.Integertimes.Thisfilesystemusestheindexstructure,inode,torefertotheext2filesystemintheLinuxsystem.Itorganizesfilesinanindexstructure,avoidingthedisadvantageofaccessingadatablockandre-tracingallpreviousdatablocks.Inthedevelopmentofthefilesystem,aharddiskdriverwasimplemented.Basedonthepreviouslywrittensystemkernel,thefilesystemwasdevelopedinClanguageandthecompilerenvironmentwasgcc.Thenthecodewasdebuggedonthebochsvirtualmachine.Eventuallyitispossibletocreatefiles,openandclosefiles,writefiles,readfiles,implementfiledeletionfunctions,createdirectories,traversedirectories,deletedirectories,workdirectoryoftasks,getfileattributes,etc.Features.Keywords:Filesystem,inode,Clanguage,gcc,bochsvirtualmachine長春工程學(xué)院畢業(yè)設(shè)計(論文)引言1.1項目開發(fā)背景隨著科技不斷的進(jìn)步,我們?nèi)粘P枰幚淼奈募苍絹碓酱?,這個時候就凸顯了文件系統(tǒng)的重要性。在操作系統(tǒng)中,文件系統(tǒng)的主要目的是實現(xiàn)對文件的按名存取。如果一個硬盤上沒有一個良好的文件系統(tǒng),這將是一個難以想象的結(jié)果。因為硬盤是一個低速設(shè)備,而CPU和內(nèi)存都是高速設(shè)備,這就需要操作系統(tǒng)中的文件系統(tǒng)對文件進(jìn)行良好的組織,實現(xiàn)對文件的正確操作。1.2選題目的文件系統(tǒng)的主要目的是實現(xiàn)對文件的按名存取,是操作系統(tǒng)中對分區(qū)上的文件的方法和數(shù)據(jù)結(jié)構(gòu)。本次畢業(yè)設(shè)計選擇“基于bochs虛擬機(jī)的文件系統(tǒng)的實現(xiàn)與設(shè)計”這個題目的目的在于研究文件系統(tǒng)的基本原理,為以后的學(xué)習(xí)工作打下基礎(chǔ),本文件系統(tǒng)采用索引結(jié)構(gòu)——inode,參照Linux系統(tǒng)中的ext2文件系統(tǒng),它將文件以索引結(jié)構(gòu)來組織,避免了訪問某一數(shù)據(jù)塊需要從頭把其前所有數(shù)據(jù)塊再遍歷一次的缺點。通過模擬文件系統(tǒng)的實現(xiàn),深入理解操作系統(tǒng)中文件系統(tǒng)的理論知識,加深對教材中的重要算法的理解。同時通過編程實現(xiàn)這些算法,更好地掌握操作系統(tǒng)的原理及實現(xiàn)方法,提高綜合運用各專業(yè)課知識的能力。1.3設(shè)計思想本文件系統(tǒng)完全基于自己實現(xiàn)的操作系統(tǒng),從編寫MBR引導(dǎo)記錄,到加載內(nèi)核,實現(xiàn)中斷、進(jìn)程線程、I/O系統(tǒng)、內(nèi)存管理,到實現(xiàn)硬盤驅(qū)動程序,最終在以上基礎(chǔ)上實現(xiàn)自己的文件系統(tǒng),完成了文件系統(tǒng)所必須的功能:創(chuàng)建文件系統(tǒng)、創(chuàng)建文件、文件的打開與關(guān)閉、實現(xiàn)文件寫入、讀取文件、實現(xiàn)文件讀寫指針定位功能、實現(xiàn)文件刪除功能、創(chuàng)建目錄、遍歷目錄、刪除目錄、任務(wù)的工作目錄、獲得文件屬性等。2系統(tǒng)分析2.1系統(tǒng)開發(fā)及運行環(huán)境使用CentOS6.3作為開發(fā)環(huán)境,使用C語言,gcc作為開發(fā)工具,在bochs虛擬機(jī)上進(jìn)行調(diào)試運行。2.2系統(tǒng)應(yīng)用技術(shù)闡述CentOS(CommunityEnterpriseOperatingSystem,中文意思是:社區(qū)企業(yè)操作系統(tǒng))是Linux發(fā)行版之一,它是來自于RedHatEnterpriseLinux依照開放源代碼規(guī)定釋出的源代碼所編譯而成。,并且是免費的操作系統(tǒng)。GNU編譯器套件(GNUCompilerCollection),是世界頂級的編譯器,能夠支持多種語言,它是一套以GPL及LGPL許可證所發(fā)行的自由軟件,也是GNU計劃的關(guān)鍵部分。通常被認(rèn)為是跨平臺編譯器的標(biāo)準(zhǔn)。Bochs是一個以LGPL許可證發(fā)放的開源代碼的x86、x86-64IBMPC兼容機(jī)模擬器和調(diào)試工具。它支持處理器(包括保護(hù)模式)、內(nèi)存、硬盤、顯示器、以太網(wǎng)、BIOS、IBMPC兼容機(jī)的常見硬件外設(shè)的仿真。Bochs主要用于操作系統(tǒng)開發(fā)(當(dāng)一個模擬器操作系統(tǒng)崩潰,它不崩潰主機(jī)操作系統(tǒng),所以可以調(diào)試仿真操作系統(tǒng))和在主機(jī)操作系統(tǒng)運行其他來賓操作系統(tǒng)。它也可以用來運行不兼容的舊的軟件。2.3系統(tǒng)可行性分析技術(shù)可行性:文件系統(tǒng)在CentOS免費操作系統(tǒng)上開發(fā),開發(fā)語言選擇C語言,開發(fā)工具選擇GCC。本系統(tǒng)的設(shè)計與開發(fā)在技術(shù)條件上都是滿足的,因此,它在技術(shù)上是可行的。運行可行性:現(xiàn)代的操作系統(tǒng)越來越龐大,功能越來越豐富,需要良好的文件系統(tǒng)提供對文件的管理,實現(xiàn)操作系統(tǒng)高效可靠的運行,本文件系統(tǒng),所耗費的資源非常的小,電腦無論是在硬件方面還是在軟件方面都能夠滿足條件,因此,文件系統(tǒng)是具備運行可行性的。經(jīng)濟(jì)可行性:經(jīng)過分析設(shè)計,能夠在一定程度上減少經(jīng)濟(jì)開支?,F(xiàn)在,計算機(jī)的成本十分低廉,性能卻非常強(qiáng)大而且高效。文件系統(tǒng)將給操作系統(tǒng)的運行效率上帶來新的質(zhì)的飛躍,減少硬件資源的開銷。2.4系統(tǒng)性能要求本文件系統(tǒng)對性能的要求非常低,在整個文件系統(tǒng)開發(fā)的過程中,使用bochs虛擬機(jī)模擬的硬件資源為:32MB內(nèi)存,60M主盤,80M從盤。主盤用來安裝內(nèi)核,從盤安裝文件系統(tǒng)。3系統(tǒng)總體設(shè)計3.1系統(tǒng)開發(fā)的準(zhǔn)備工作由于本文件系統(tǒng)完全基于自己實現(xiàn)的操作系統(tǒng),從編寫MBR引導(dǎo)記錄,到加載內(nèi)核,實現(xiàn)中斷、進(jìn)程線程、I/O系統(tǒng)、內(nèi)存管理,到實現(xiàn)硬盤驅(qū)動程序,最終在以上基礎(chǔ)上實現(xiàn)自己的文件系統(tǒng),所以在正式開發(fā)文件系統(tǒng)前要做大量的基礎(chǔ)工作。3.1.1編寫MBR主引導(dǎo)記錄,讓MBR使用硬盤圖3-1mbr.S圖3-2loader.SMBR是主引導(dǎo)記錄(Master或MainBootRecord),它位于硬盤最開始的扇區(qū),即0盤0道1扇區(qū)。在MBR引導(dǎo)扇區(qū)中的內(nèi)容是:446字節(jié)的引導(dǎo)程序及參數(shù);4字節(jié)的分區(qū)表;2字節(jié)結(jié)束標(biāo)記0x55和0xaa。在MBR引導(dǎo)程序中,能夠從BIOS手中接下系統(tǒng)的控制權(quán),之所以BIOS能夠把系統(tǒng)的控制權(quán)移交給MBR,是因為BIOS知道在0盤0道1扇區(qū)處存在MBR,然后將引導(dǎo)程序加載到0x7c00的物理地址處,這是約定好的內(nèi)容。在mbr.S中實現(xiàn)了對硬盤的操作,完成第一棒任務(wù),從BIOS手里接過系統(tǒng)的控制權(quán),然后在0x900處加載loader。loader.S很簡單,只是在屏幕上顯示了綠色閃爍背景,前景為紅色的字符串“2loader”。運行結(jié)果如圖3-3所示:圖3-3loader運行結(jié)果3.1.2打開保護(hù)模式,加載內(nèi)核進(jìn)入到保護(hù)模式之后,啟用內(nèi)存分頁機(jī)制,由于實現(xiàn)的操作系統(tǒng)是32位的,每個進(jìn)程都將會擁有4GB的虛擬內(nèi)存空間并且進(jìn)一步的完善內(nèi)核,實現(xiàn)了字符、字符串、整數(shù)的打印,運行結(jié)果如圖3-4所示:圖3-4進(jìn)入保護(hù)模式3.1.3中斷現(xiàn)代的操作系統(tǒng)是中斷驅(qū)動的,如果沒有中斷,操作系統(tǒng)幾乎什么都做不了,操作系統(tǒng)可以說就是個死循環(huán),在此實現(xiàn)了中斷,用到了可編程中斷控制器8259A和可編程計數(shù)器/定時器8253。圖3-5kernel.S運行結(jié)果如圖3-6所示:圖3-6中斷3.1.4內(nèi)存管理在本操作系統(tǒng)中使用位圖來管理內(nèi)存,從內(nèi)存池的規(guī)劃,分配頁內(nèi)存,到堆內(nèi)存的管理,在測試代碼中申請3頁內(nèi)存,運行結(jié)果如圖3-7所示:圖3-7內(nèi)存管理3.1.5線程及I/O系統(tǒng)使用時間片輪轉(zhuǎn)算法來進(jìn)行調(diào)度,同時實現(xiàn)了鎖的機(jī)制,在main函數(shù)中測試如圖3-8所示:圖3-8線程編寫鍵盤驅(qū)動程序,實現(xiàn)鍵盤輸入圖3-9keyboard.c在鍵盤中鍵入字符如圖所示:圖3-10鍵盤輸入3.1.6用戶進(jìn)程此前的所有操作都是在最高的特權(quán)級0級下工作,意味著任何程序都和操作系統(tǒng)平起平坐,本節(jié)實現(xiàn)用戶進(jìn)程,要在特權(quán)級3級下工作。定義并初始化TSS,創(chuàng)建用戶進(jìn)程后結(jié)果如圖所示:圖3-11用戶進(jìn)程3.1.7編寫硬盤驅(qū)動程序要想實現(xiàn)文件系統(tǒng),必須要有一套完整的方法,就是硬盤驅(qū)動程序。之前所有的操作都是在hd60M.img這個硬盤上,但是它的作用是啟動盤,來存儲內(nèi)核,沒有文件系統(tǒng)的裸盤,為了降低難度,新創(chuàng)建一個hd80M.img,將文件系統(tǒng)安裝在此。使用bochs虛擬機(jī)的bximage命令新建一個硬盤,然后再配置文件中添加這個硬盤的信息。使用fdisk命令對hd80M.img進(jìn)行分區(qū)操作,有1個主分區(qū)和4個邏輯分區(qū),分區(qū)結(jié)果如圖3-12所示:圖3-12keyboard.c驅(qū)動程序是對硬件接口的封裝,它把參數(shù)設(shè)置的重復(fù)、枯燥、復(fù)雜的過程封裝成一個過程,避免每次執(zhí)行命令時都重復(fù)做這些工作。硬盤的驅(qū)動程序?qū)τ脖P的接口進(jìn)行了封裝。圖3-13ide.hide.h定義了硬盤相關(guān)的數(shù)據(jù)結(jié)構(gòu),包含了分區(qū)結(jié)構(gòu),硬盤結(jié)構(gòu),ata通道結(jié)構(gòu)。然后編寫ide.c實現(xiàn)硬盤驅(qū)動程序,運行結(jié)果如圖3-14所示:圖3-14ide.h3.2系統(tǒng)功能結(jié)構(gòu)圖3-15文件系統(tǒng)的功能結(jié)構(gòu)3.3系統(tǒng)功能設(shè)計創(chuàng)建文件系統(tǒng):對一塊硬盤進(jìn)行檢查,不論是否存在文件系統(tǒng),一律進(jìn)行格式化,安裝自己的文件系統(tǒng)。文件描述符:Linux中所有文件操作都基于文件描述符,其中包含文件偏移量、文件的打開標(biāo)志、inode指針。文件操作相關(guān)的基礎(chǔ)函數(shù):inode操作相關(guān)、文件相關(guān)、目錄相關(guān)、路徑解析相關(guān)、文件檢索相關(guān)的函數(shù)。創(chuàng)建文件:在文件系統(tǒng)上創(chuàng)建普通文件,若文件已經(jīng)存在,則提示文件已存在,即不能夠在同一目錄下創(chuàng)建同名文件。文件的打開與關(guān)閉:實現(xiàn)對文件的打開和關(guān)閉。執(zhí)行打開操作時,若有其他進(jìn)程正在操作文件,則提示文件正在被操作,請稍后再試。文件的寫入:實現(xiàn)向文件中寫入內(nèi)容。寫入時,如果在同一扇區(qū)內(nèi)寫入數(shù)據(jù),不涉及到分配新扇區(qū),如果涉及到分配新扇區(qū)要考慮三種情況:第一種情況,12個直接塊公用;第二種情況,舊數(shù)據(jù)在12個直接塊內(nèi),新數(shù)據(jù)將使用間接塊;第三種情況,新數(shù)據(jù)占據(jù)間接塊。讀取文件:實現(xiàn)讀取已經(jīng)存在的文件里的內(nèi)容。與文件的寫入類似,數(shù)據(jù)在同一扇區(qū)內(nèi),如果要讀取多個扇區(qū)要考慮三種情況:第一種情況,起始塊和終止塊屬于直接塊;第二種情況,待讀入的數(shù)據(jù)跨越直接塊和間接塊兩類;第三種情況,數(shù)據(jù)在間接塊中。文件讀寫指針定位功能:對已經(jīng)讀取的文件,不用關(guān)閉文件再次打開就能夠直接從指定位置讀寫文件內(nèi)容。文件的刪除:實現(xiàn)刪除已經(jīng)存在的文件。如果文件正在使用,不能刪除,如果刪除失敗給出文字提示。創(chuàng)建目錄:實現(xiàn)創(chuàng)建新的目錄功能。如果目錄存在則創(chuàng)建失敗,或者給出的路徑錯誤也將創(chuàng)建失敗。遍歷目錄:實現(xiàn)遍歷目錄功能。輸出給出的路徑每一級時目錄還是文件信息,同時給出相應(yīng)的提示信息。刪除目錄:實現(xiàn)刪除目錄的功能。刪除已經(jīng)存在的目錄,如果目錄非空則不能刪除,提示刪除失敗。任務(wù)的工作目錄:實現(xiàn)使用“pwd”命令獲取當(dāng)前工作目錄,使用“cd”命令改變當(dāng)前工作目錄。獲取文件屬性:實現(xiàn)使用“l(fā)s”命令顯示文件屬性,并且支持“-h”和“-l”可選參數(shù)。簡單的shell:實現(xiàn)簡單的shell,完成系統(tǒng)交互操作。4系統(tǒng)詳細(xì)設(shè)計4.1創(chuàng)建文件系統(tǒng)在硬盤hd80M.img的各個分區(qū)上創(chuàng)建文件系統(tǒng),往后的文件操作都基于此工作。4.1.1創(chuàng)建超級快、i結(jié)點、目錄項在建立文件系統(tǒng)之前,需要先創(chuàng)建超級快、i結(jié)點、目錄項,他們是基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)。圖4-1super_block.h為了以后方便寫程序,將數(shù)據(jù)塊大小與扇區(qū)大小設(shè)置一致,即1塊等于1扇區(qū)。本文件系統(tǒng)是參照ext2文件系統(tǒng),但是超級塊并沒有ext2文件系統(tǒng)的超級塊那么復(fù)雜,只用到了一些必要的內(nèi)容,大小連1個扇區(qū)都不到,但是硬盤的操作都是以扇區(qū)為單位進(jìn)行的,所以交給硬盤的數(shù)據(jù)大小必須要是扇區(qū)大小的整數(shù)倍。為了湊足1個扇區(qū)(即512字節(jié)),在super_block.h的最后定義了460字節(jié)的pad數(shù)組,來填充扇區(qū)。并且為了保證在編譯后超級快的大小為512字節(jié),在最后使用了__attribute__((packed))。圖4-2inode.h在inode.h中,i_no是inode的編號,這是inode數(shù)組中的下標(biāo)。i_size指的是這個inode所指的文件的大小,inode也用來指代目錄,所以說當(dāng)inode指代普通文件是,i_size表示文件大小,當(dāng)inode表示的是目錄時,i_size表示的是此目錄中所有的目錄項大小之和。i_open_cnts記錄文件打開的次數(shù),與回收資源有關(guān),見后。write_deny是為了保證文件能夠進(jìn)行正確的寫操作,用來限制文件的操作的。只有當(dāng)write_deny為false時,才能對此文件進(jìn)行寫操作。i_sectors是表示數(shù)據(jù)塊的指針,i_sectors[0-11]是直接塊,i_sectors[12]用來存儲一級間接塊指針,在此文件系統(tǒng)中只支持一級間接塊,扇區(qū)大小為512字節(jié),塊地址用4字節(jié)表示,因此支持128個一級間接塊,所以一共支持128+12=140個塊(扇區(qū))。inode_tag表示已經(jīng)打開的inode列表,由于inode是在硬盤上,速度比較慢,所以inode_tag用于緩存的作用。圖4-3dir.hstructdir表示目錄結(jié)構(gòu)此內(nèi)容在此定義,在后續(xù)操作時詳解。structdir_entry表示目錄項結(jié)構(gòu),文件的名字最長為16個字符,i_no表示inode編號,file_typesf_type表示文件的類型,它是枚舉類型,在fs.h中定義。圖4-4fs.h開頭定義一些用到的宏,方便編碼,然后定義了文件的類型,F(xiàn)T_UNKNOWN=0,(不支持的文件類型),F(xiàn)T_REGULAR=1(普通文件),F(xiàn)T_DIRECTORY=2(目錄)。4.1.2創(chuàng)建文件系統(tǒng)圖4-5fs.c(fs.c中的部分代碼)創(chuàng)建文件系統(tǒng)也就是所謂的高級格式化分區(qū),fs.c中用partition_format函數(shù)來完成格式化,這個函數(shù)的主要功能實際上就是按照對文件系統(tǒng)的規(guī)劃,將硬盤每一個分區(qū)中的信息進(jìn)行了初始化。這些數(shù)據(jù)就是用來記錄硬盤分區(qū)的基本信息,將信息確定并保留下來。然后使用filesys_init函數(shù)完成初始化信息,創(chuàng)建文件系統(tǒng)就是創(chuàng)建必要的信息,有超級塊位置及其大小,空閑塊位置及其大小,inode位圖的位置及其大小,inode數(shù)組的位置及其大小,空閑塊起始地址,根目錄起始地址。關(guān)鍵步驟有以下步驟:根據(jù)分區(qū)part大小,計算分區(qū)文件系統(tǒng)各元信息需要的扇區(qū)數(shù)及位置。在內(nèi)存中創(chuàng)建超級塊,將以上步驟計算的元信息寫入超級塊。將超級塊寫入磁盤。將元信息寫入磁盤上各自的位置。將根目錄寫入磁盤。完成以上步驟之后,運行代碼就可以看到分區(qū)格式化的結(jié)果,如下圖。圖4-6分區(qū)1圖4-7分區(qū)2圖4-6是第一次運行的結(jié)果,有1個主分區(qū),5個邏輯分區(qū),再次運行因為已經(jīng)有所定義的文件系統(tǒng)了,就不會再進(jìn)行格式化了,如圖4-7。4.1.3掛載分區(qū)在windows操作系統(tǒng)中,能夠看到分區(qū)盤符C、D、E等,但是在Linux操作系統(tǒng)中與之不同,需要使用mount和umount來掛載或者卸載新的分區(qū)。本操作系統(tǒng)的是安裝在裸盤hd60M.img上的,也就是說操作系統(tǒng)不再文件系統(tǒng)上,所以實現(xiàn)掛載就是直接選擇所要操作的分區(qū)就可以。圖4-8mount_partition函數(shù)在filesys_init函數(shù)中添加所要操作的分區(qū)“sdb1”,在list_traversal中調(diào)用mount_partition函數(shù),來實現(xiàn)分區(qū)的掛載,運行之后的結(jié)果如圖4-9所示。圖4-9掛載分區(qū)4.2文件描述符4.2.1文件描述符原理表4-1文件描述符邏輯結(jié)構(gòu)fd_pos//文件偏移量fd_flag//文件打開的標(biāo)志fd_inode//inode指針...圖4-10文件描述符與inode的關(guān)聯(lián)關(guān)系文件描述符與inode的關(guān)聯(lián)關(guān)系如圖4-9所示,根據(jù)此圖展開后續(xù)工作。4.2.2文件描述符的實現(xiàn)首先要修改thread.h代碼,修改部分如圖4-10所示。圖4-11thread.h修改部分fd_table就是文件描述符數(shù)組,大小為MAX_FILES_OPEN_PER_PROC,值為8,表示每個任務(wù)最多可以打開8個文件。然后再init_thread函數(shù)中對此初始化,如圖4-11.圖4-12init_thread函數(shù)修改部分其中0,1,2分別表示標(biāo)準(zhǔn)輸入、輸出、錯誤,-1表示該文件描述符可分配。4.3文件操作相關(guān)的基礎(chǔ)函數(shù)在實現(xiàn)文件和目錄的創(chuàng)建、打開、讀寫操作等,需要先創(chuàng)建一系列的相關(guān)基礎(chǔ)函數(shù)。4.3.1inode操作有關(guān)的函數(shù)圖4-13inode.c部分代碼圖4-14inode.c中的函數(shù)在inode.c中有inode_locate、inode_sync、inode_open、inode_close、inode_init等五個函數(shù)。inode_locate函數(shù)用來獲取inode所在的扇區(qū)和扇區(qū)內(nèi)的偏移量,inode_sync函數(shù)用來將inode寫入到分區(qū)part,inode_open函數(shù)是根據(jù)i結(jié)點號返回相應(yīng)的i結(jié)點,inode_close函數(shù)是關(guān)閉inode或減少inode的打開數(shù),inode_init函數(shù)是初始化new_inode。4.3.2文件相關(guān)的函數(shù)圖4-15file.h基本信息如代碼的注釋說明,structfile用來表示文件結(jié)構(gòu),MAX_FILE_OPEN用來表示系統(tǒng)可打開的最大文件數(shù)等。圖4-16file.c部分代碼圖4-17file.c中的函數(shù)file.c文件中有:get_free_slot_in_global函數(shù)從文件表file_table中獲取一個空閑位,成功返回下標(biāo),失敗返回-1,pcb_fd_install函數(shù)將全局描述符下標(biāo)安裝到進(jìn)程或線程自己的文件描述符數(shù)組fd_table中,成功返回下標(biāo),失敗返回-1,inode_bitmap_alloc函數(shù)分配一個i結(jié)點,返回i結(jié)點號,block_bitmap_alloc函數(shù)分配1個扇區(qū),返回其扇區(qū)地址,bitmap_sync函數(shù)將內(nèi)存中bitmap第bit_idx位所在的512字節(jié)同步到硬盤,file_create函數(shù)創(chuàng)建文件,若成功則返回文件描述符,否則返回-1。4.3.3目錄相關(guān)的函數(shù)圖4-18dir.c部分代碼圖4-19dir.c中的函數(shù)dir.c文件中有:open_root_dir函數(shù)打開根目錄,dir_open函數(shù)在分區(qū)part上打開i結(jié)點為inode_no的目錄并返回目錄指針,search_dir_entry函數(shù)在part分區(qū)內(nèi)的pdir目錄內(nèi)尋找名為name的文件或目錄,找到后返回true并將其目錄項存入dir_e,否則返回false,dir_close函數(shù)關(guān)閉目錄,create_dir_entry函數(shù)在內(nèi)存中初始化目錄項p_de,sync_dir_entry函數(shù)將目錄項p_de寫入父目錄parent_dir中,io_buf由主調(diào)函數(shù)提供。4.3.4路徑解析相關(guān)的函數(shù)圖4-20path_parse和path_depth_cnt函數(shù)path_parse函數(shù)將最上層路徑名稱解析出來,path_depth_cnt函數(shù)返回路徑深度,比如/a/b/c,深度為3。4.3.5實現(xiàn)文件檢索功能圖4-21fs.h如注釋所示。圖4-22fs.csearch_file函數(shù)搜索文件pathname,若找到則返回其inode號,否則返回-1。4.4創(chuàng)建文件本節(jié)實現(xiàn)創(chuàng)建文件,不包括創(chuàng)建目錄。4.4.1實現(xiàn)file_create在file.c中增加一個函數(shù)file_create。創(chuàng)建文件需要考慮以下幾個方面:創(chuàng)建其inode;文件需要扇區(qū)地址;文件所在的目錄要增加一個目錄項大??;如果操作失敗需要進(jìn)行回滾操作;將在內(nèi)存中的操作同步到硬盤之中。圖4-23file_create函數(shù)file_create函數(shù)創(chuàng)建文件,若成功則返回文件描述符,否則返回-1。4.4.2實現(xiàn)sys_opensys_open是open函數(shù)的內(nèi)核級實現(xiàn),實現(xiàn)系統(tǒng)調(diào)用,不僅能夠打開文件,還能創(chuàng)建新的文件。圖4-24sys_open函數(shù)sys_open函數(shù)打開或創(chuàng)建文件成功后,返回文件描述符,否則返回-1。然后在filesys_init函數(shù)中添加一些初始化的信息,如圖4-25所示。圖4-25filesys_init添加部分4.4.3在文件系統(tǒng)上創(chuàng)建第一個文件在main.c中加入sys_open的調(diào)用,見圖4-26.圖4-26main函數(shù)創(chuàng)建文件前,根目錄的扇區(qū)地址是十六進(jìn)制0x2aa,將其乘以512后,十進(jìn)制結(jié)果是349184,接著用xxd.sh查看hd80M.img偏移349184字節(jié)處的512字節(jié)的內(nèi)容。目錄中的內(nèi)容是目錄項,每個目錄項包括三部分的內(nèi)容:16字節(jié)的文件名filename,4字節(jié)的inode編號i_no,4字節(jié)的文件類型f_type。如圖4-27中,0x55400字節(jié)處的連續(xù)24字節(jié),其中低16位中除最低處是0x2e,其他都是0,這16字節(jié)是目錄項中的文件名filename,0x2e是字符‘.’的ASCII碼,緊接著是根目錄inode編號0,表示‘.’,最后4字節(jié)是文件類型f_type,其值為2,表示‘.’是目錄類型FT_DIRECTORY。運行程序創(chuàng)建文件如圖4-27所示:圖4-27創(chuàng)建文件如圖4-28,同樣的查看偏移0x55430的地方是第三個文件file1的目錄項,在圖中右半邊部分可以看到可讀字符file1。圖4-28根目錄產(chǎn)生了新文件圖4-29表示在同一目錄下不能創(chuàng)建同名文件圖4-29無法創(chuàng)建同名文件4.5文件的打開與關(guān)閉繼續(xù)改進(jìn)sys_open,實現(xiàn)更多的功能。4.5.1文件的打開圖4-30file_open函數(shù)file_open函數(shù)接受2個參數(shù),打開編號為inode_no的inode對應(yīng)的文件,若成功則返回文件描述符,否則返回-1。圖4-31sys_open函數(shù)修改部分修改了判斷flag的switch結(jié)構(gòu),支持O_RDONLY,O_WRONLY,O_RDWR操作。4.5.2文件的關(guān)閉圖4-32file_close函數(shù)file_open函數(shù)接受1個參數(shù),關(guān)閉文件。圖4-33fd_local2global和sys_close函數(shù)fd_local2global函數(shù)將文件描述符轉(zhuǎn)化為文件表的下標(biāo),sys_close函數(shù)關(guān)閉文件描述符fd指向的文件,成功返回0,否則返回-1。然后在main函數(shù)中調(diào)用sy_open函數(shù),如圖4-34所示。圖4-34文件打開與關(guān)閉4.6實現(xiàn)文件的寫入在最開始的write只是一個簡單的版本,在這里要添加支持文件描述符,還要修改一些周邊與此調(diào)用相關(guān)的內(nèi)容。4.6.1實現(xiàn)file_write圖4-35file_write函數(shù)file_write函數(shù)比較長,只截圖了部分內(nèi)容,主要功能是把buf中的count個字節(jié)寫入file,成功則返回寫入的字節(jié)數(shù),失敗則返回-1。4.6.2改進(jìn)sys_write及write系統(tǒng)調(diào)用圖4-36sys_write函數(shù)sys_write函數(shù)將buf中連續(xù)count個字節(jié)寫入文件描述符fd,成功則返回寫入的字節(jié)數(shù),失敗返回-1。相應(yīng)的還要修改系統(tǒng)調(diào)用相關(guān)的內(nèi)容,如圖4-37和4-38。圖4-37write函數(shù)圖4-38printf函數(shù)4.6.3把數(shù)據(jù)寫入文件修改main.c。圖4-39main函數(shù)圖4-40文件寫入演示圖4-40中輸出寫入的扇區(qū)地址是0x2ab,用xxd工具查看該地址處的數(shù)據(jù),同時查看inode_table的地址,該地址是0x4a。在圖4-41中的上半部分是查看文件寫入的數(shù)據(jù)。將扇區(qū)地址0x2ab換算為字節(jié)是349696,用xxd腳本查看hd80M.img的該地址處的1扇區(qū),xxd在右邊顯示了字符“hello,world”,但‘\n’是不可見字符,因此只是以‘.’代替。圖4-41的下半部分是查看inode_table中的前兩個inode,目的是查看inode的i_size和i_sectors中的地址。圖4-41inode及文件數(shù)據(jù)驗證在此運行程序,會發(fā)現(xiàn)file1中的內(nèi)容變成了兩個“hello,world\n”,如圖4-42所示:圖4-42數(shù)據(jù)變化4.7讀取文件4.7.1實現(xiàn)file_read圖4-43file_read函數(shù)file_read函數(shù)從文件file中讀取count個字節(jié)寫入buf,返回讀出的字節(jié)數(shù),若到文件尾則返回-1。4.7.2實現(xiàn)sys_read與功能驗證圖4-44sys_read函數(shù)緊接著修改mian函數(shù)圖4-45main函數(shù)之前文件file1中已經(jīng)寫入24字節(jié)的內(nèi)容,兩個“hello,world\n”。在main函數(shù)中27-31行,從文件中讀出“hello,world\nhello,”,33-35讀出剩下的6字節(jié)“world\n”。然后再39行打印出-1說明沒有數(shù)據(jù)了。42行關(guān)閉文件,43-46重新讀出24字節(jié)內(nèi)容“hello,world\nhello,world\n”,運行結(jié)果如圖4-46所示。圖4-46讀取文件內(nèi)容4.8實現(xiàn)文件讀寫指針定位功能在上一節(jié)中文件讀取完畢后必須關(guān)閉后再打開才可以讀取文件的內(nèi)容,本節(jié)實現(xiàn)文件讀寫指針定位功能,本質(zhì)上就是實現(xiàn)設(shè)置文件讀寫是的其實偏移量。圖4-47文件讀寫位置偏移量SEEK_SET,offset的參照物是文件開始處;SEEK_CUR,offset的參照物是當(dāng)前讀寫位;SEEK_END,offset的參照物是文件尺寸的大小。圖4-48sys_lseek函數(shù)sys_lseek函數(shù)重置用于文件讀寫操作的偏移指針,成功時返回新的偏移量,出錯時返回-1,然后修改main函數(shù)。圖4-49main函數(shù)修改部分圖4-50重新讀取文件的結(jié)果4.9實現(xiàn)文件刪除功能在Linux中刪除文件的函數(shù)式unlink,本節(jié)實現(xiàn)它。刪除文件就是創(chuàng)建文件的逆過程,關(guān)系到inode、inode位圖、目錄inode中的i_size、目錄項、數(shù)據(jù)塊及數(shù)據(jù)塊位圖的回收操作。4.9.1回收inode圖4-51inode_delete和inode_release函數(shù)inode是文件核心部分,刪除一個文件關(guān)鍵部分就是刪除inode,相關(guān)資源有:inode位圖;inode_table;inode中i_sectors[0-11]中的直接塊和一級間接索引塊表i_sectors[12]中的間接塊;一級間接索引塊表的扇區(qū)地址。inode_delete函數(shù)將硬盤分區(qū)part上的inode清空,inode_release函數(shù)回收inode的數(shù)據(jù)塊和inode本身。實際上inode_delete不是必須的,在此做測試用。4.9.2刪除目錄項圖4-52delete_dir_entry函數(shù)文件名與目錄項有關(guān),所以刪除文件要將目錄中的目錄項刪除,與此相關(guān)內(nèi)容有:將目錄項置為0;根目錄不能刪除,必須保留一個塊;目錄inode的i_size是目錄項大小的總和,所以減去一個目錄項的單位大?。蛔詈笠獙⑺鞑僮魍降接脖P。delete_dir_entry函數(shù)把分區(qū)part目錄pdir中編號為inode_no的目錄項刪除。4.9.3實現(xiàn)sys_unlink與功能驗證圖4-53sys_unlink函數(shù)圖4-54main函數(shù)實現(xiàn)內(nèi)核部分的sys_unlink函數(shù)以及修改main函數(shù),測試如下圖所示:圖4-55文件元信息(刪除文件前)圖4-55是在文件刪除前截取下來的信息,顯示了塊位圖扇區(qū)地址是0x41,inode位圖扇區(qū)地址是0x49,inode_tanle地址是0x4a,根目錄扇區(qū)地址是0x2aa。塊位圖中的值是3,說明分配了2個塊,一個分配給了根目錄的i_sectors[0],另一個分配給了/file1的i_sectors[0]。Inode為圖中的值也是3,同樣是分別分配給了根目錄和/file1的inode。運行程序后輸出“/file1deletedone!\n”,如圖4-56所示:圖4-56刪除文件圖4-57對比圖4-55,塊位圖和inode位圖都由3變成了1,這說明file1所占的塊被回收,inode也被回收了,inode_table和根目錄中也沒有相應(yīng)的信息了。圖4-57文件元信息(刪除文件后)4.10創(chuàng)建目錄4.10.1實現(xiàn)sys_mkdir創(chuàng)建目錄在Linux中是用mkdir來創(chuàng)建目錄,其原型是“intmkdir(constchar*pathname,mode_tmode)”,panthname是待創(chuàng)建的目錄名,mode是所創(chuàng)建目錄的權(quán)限,本節(jié)實現(xiàn)sys_mkdir函數(shù),不支持權(quán)限參數(shù)。圖4-58sys_mkdir函數(shù)創(chuàng)建目錄的過程有:確認(rèn)待創(chuàng)建的目錄不存在;創(chuàng)建新的inode;分配1個目錄項;創(chuàng)建兩個目錄項“.”和“..”;在父目錄中添加新目錄的目錄項;將所做操作同步到硬盤。sys_mkdir函數(shù)創(chuàng)建目錄pathname,成功返回0,失敗返回-1。4.10.2創(chuàng)建目錄驗證功能由于上一節(jié)把/file刪除了,在本節(jié)做測試之前,重新創(chuàng)建/file,修改main函數(shù),如下圖:圖4-59main函數(shù)運行結(jié)果如下圖:圖4-60目錄創(chuàng)建目前沒有目錄“/dir1”,因此直接創(chuàng)建“/dir1/subdir1”會失敗。圖4-61創(chuàng)建目錄后根目錄中的目錄項圖4-61中,對比沒有創(chuàng)建dir1前的根目錄,此處多了目錄dir1。圖4-62中到inode_table中查看02個inode的信息,緊著通過圖4-62、4-63、4-64一步步追蹤,最終找到文件file2,看到其中的內(nèi)容“Catchmeifyoucan!”。圖4-62inode_table中的inode圖4-63/dir1中的目錄項圖4-64/dir1/subdir1/file2的目錄項圖4-65dir1/subdir1/file2的內(nèi)容4.11遍歷目錄4.11.1打開目錄和關(guān)閉目錄在Linux中是用opendir和closedir完成打開和關(guān)閉目錄的,本節(jié)實現(xiàn)這兩個函數(shù)的內(nèi)核部分sys_opendir和sys_closedir。圖4-66sys_opendir函數(shù)sys_opendir函數(shù)目錄打開成功后返回目錄指針,失敗返回NULL。圖4-67sys_closedir函數(shù)sys_closedir函數(shù)成功關(guān)閉目錄dir返回0,失敗返回-1。編譯運行如圖4-68所示:圖4-68目錄打開與關(guān)閉4.11.2讀取1個目錄項圖4-69dir_read函數(shù)dir_read函數(shù)讀取目錄,成功返回1個目錄項,失敗返回NULL。4.11.3實現(xiàn)sys_readdir及sys_rewinddir圖4-70sys_readdir和sys_rewinddir函數(shù)sys_readdir函數(shù)是dir_read的封裝,為了實現(xiàn)系統(tǒng)調(diào)用命名風(fēng)格的統(tǒng)一,讀取目錄dir的1個目錄項,成功后返回其目錄項地址,到目錄尾時或出錯時返回NULL。sys_rewinddir函數(shù)把目錄dir的指針dir_pos置0。圖4-71main函數(shù)在main函數(shù)中先打開目錄“/dir/subdir1”,然后判斷其類型,運行結(jié)果如圖4-69所示:圖4-72遍歷目錄運行結(jié)果4.12刪除目錄4.12.1刪除目錄與判斷空目錄圖4-73dir_is_empty和dir_remove函數(shù)dir_is_empty函數(shù)判斷目錄是否為空。dir_remove函數(shù)在父目錄parent_dir中刪除child_dir。4.12.2實現(xiàn)sys_rmdir及驗證功能圖4-74sys_rmdir函數(shù)sys_rmdir函數(shù)刪除空目錄,成功時返回0,失敗時返回-1。圖4-75sys_rmdir函數(shù)運行結(jié)果如圖4-76:圖4-76刪除目錄運行結(jié)果4.13任務(wù)的工作目錄4.13.1顯示當(dāng)前工作目錄的原理及基礎(chǔ)代碼圖4-77get_parent_dir_inode_nr和get_child_dir_name函數(shù)get_parent_dir_inode_nr函數(shù)獲得父目錄的inode編號。get_child_dir_name函數(shù)在inode編號為p_inode_nr的目錄中查找inode編號為c_inode_nr的子目錄的名字,將名字存入緩沖區(qū)path.成功返回0,失敗返-1。4.13.2實現(xiàn)sys_getcwp首先要修改pcb及初始化進(jìn)程信息:圖4-78pcb圖4-79初始化進(jìn)程信息圖4-80sys_getcwd函數(shù)sys_getcwd函數(shù)把當(dāng)前工作目錄絕對路徑寫入buf,size是buf的大小。當(dāng)buf為NULL時,由操作系統(tǒng)分配存儲工作路徑的空間并返回地址失敗則返回NULL。4.13.3實現(xiàn)sys_chdir改變工作目錄圖4-81sys_chdir函數(shù)sys_chdir函數(shù)更改當(dāng)前工作目錄為絕對路徑path,成功則返回0,失敗返回-1。圖4-82main函數(shù)運行結(jié)果如圖4-79所示:圖4-83改變工作目錄運行結(jié)果4.14獲得文件屬性4.14.1實現(xiàn)sys_stat圖4-84stat結(jié)構(gòu)體圖4-85sys_stat函數(shù)sys_stat函數(shù)在buf中填充文件結(jié)構(gòu)相關(guān)信息,成功時返回0,失敗返回-1。圖4-86main函數(shù)運行結(jié)果如圖4-87所示:圖4-87sys_stat運行結(jié)果4.15實現(xiàn)簡單的shell4.15.1shell雛形圖4-88shell.c在本節(jié)的shell中只能夠?qū)崿F(xiàn)一個shell的雛形,并不能進(jìn)行任何命令的操作,運行結(jié)果如圖4-89所示:圖4-89my_shell4.15.2添加Ctrl+u和Ctrl+l快捷鍵圖4-90shell.c添加Ctrl+u和Ctrl+l快捷鍵,分別實現(xiàn)清楚本次輸入的作用和清屏的作用。4.15.3解析鍵入的字符圖4-91cmd_parse函數(shù)在之前的shell中不論按下任何按鍵都不會有任何的反應(yīng),在cmd_parse函數(shù)中對鍵盤鍵入的字符進(jìn)行了解析,分析字符串cmd_str中以token為分隔符的單詞,將各單詞的指針存入argv數(shù)組,運行結(jié)果如圖4-92所示:圖4-92分析命令字符串4.15.4路徑解析轉(zhuǎn)換圖4-93cmd_parse函數(shù)路徑有絕對路徑個相對路徑兩種。在一般情況下,用戶輸入法人往往都是相對路徑,相對路徑就是以當(dāng)前工作路徑為基礎(chǔ),“當(dāng)前工作路徑+相對路徑=絕對路徑”,在本節(jié)實現(xiàn)了對輸入路徑的解析,wash_path函數(shù)將路徑old_abs_path中的..和.轉(zhuǎn)換為實際路徑后存入new_abs_path,make_clear_abs_path函數(shù)將path處理成不含..和.的絕對路徑,存儲在final_path。4.15.5實現(xiàn)ls、cd、mkdir、ps、rm、cat等命令圖4-94my_shell函數(shù)添加了一些常用的命令,如ls、cd、mkdir、ps、rm、cat等,運行結(jié)果如圖4-95所示:圖4-95shell響應(yīng)命令5系統(tǒng)測試圖5-1系統(tǒng)運行結(jié)果系統(tǒng)啟動,輸入“l(fā)s”命令,看到根目錄下的內(nèi)容,然后用“cd”命令切換到“dir1”目錄,再用“cd”命令切換回根目錄,用“mkdir”命令創(chuàng)建新目錄“new1”,用“rmdir”命令刪除“new1”目錄,用“pwd”命令能夠顯示當(dāng)前操作的目錄,用“ps”命令顯示進(jìn)程信息,系統(tǒng)基本運行穩(wěn)定,沒有出現(xiàn)錯誤。6總結(jié)接近畢業(yè)的日子,經(jīng)過我長達(dá)半年的努力,畢業(yè)設(shè)計圓滿完成。我所選擇的題目是“基于bochs虛擬機(jī)的文件系統(tǒng)的設(shè)計與實現(xiàn)”,對我來說有相當(dāng)大的難度,因為要完成一個文件系統(tǒng)需要涉及到很多的知識,為此我提早半年就著手準(zhǔn)備畢業(yè)設(shè)計,為的就是能夠做出高質(zhì)量的內(nèi)容。在準(zhǔn)備畢業(yè)設(shè)計過程中我學(xué)到了許多知識,差不多把操作系統(tǒng)的知識復(fù)習(xí)了一遍,并且自己一點點實現(xiàn)了一個操作系統(tǒng),雖然說功能比較簡陋,但是操作系統(tǒng)的核心功能該有的都有了,從BIOS到MBR,把內(nèi)核加載到內(nèi)存,內(nèi)存的管理、中斷、進(jìn)程線程、I/O系統(tǒng)等核心功能,最終在此基礎(chǔ)上編寫了硬盤驅(qū)動程序,文件系統(tǒng),還實現(xiàn)了一個簡單的shell來對系統(tǒng)進(jìn)行交互式操作,比如實現(xiàn)了cd、ls、mkdir、rmdir、rm、cat等一些常用的命令。在這次畢業(yè)設(shè)計中我對大學(xué)所學(xué)的知識幾乎復(fù)習(xí)了一遍,從硬件到軟件知識,從匯編語言到C語言的知識,尤其是在C語言中的指針部分,之前學(xué)習(xí)的時候?qū)W的并不是十分扎實,但在此次畢業(yè)設(shè)計中大量用到指針的知識,用來對地址進(jìn)行操作,所以經(jīng)過重新學(xué)習(xí)之后,對這一塊的知識已經(jīng)學(xué)的十分清楚了。同時在做畢設(shè)期間同學(xué)對我的幫助也很大,也是我和同學(xué)之間的關(guān)系更進(jìn)一步了,我們之間互相幫忙,一起討論知識,交流想法,讓我理解了團(tuán)隊的重要性。最后,在此我要感謝我的指導(dǎo)老師張東輝老師,感謝老師對我的指導(dǎo),從選題到最終出結(jié)果,老師不斷地對我指出我的不足之處。在整個畢業(yè)設(shè)計的過程中,我通過查閱大量的文獻(xiàn)資料,與其他同學(xué)交流經(jīng)驗,學(xué)到了很多知識,雖然過程艱辛。畢業(yè)設(shè)計做到最后由于自身水平有限,有一些功能還做的不夠完善,但是我會不斷更新我的系統(tǒng),堅持把這個操作系統(tǒng)做下去,這將會是我一生的財富。參考文獻(xiàn)[1]鄭鋼.操作系統(tǒng)真象還原.北京:人民郵電出版社,2016年.[2]鄭炯.Linux內(nèi)核完全剖析.北京:機(jī)械工業(yè)出版社,2006年.[3]于淵.Orange'S:一個操作系統(tǒng)的實現(xiàn).北京:電子工業(yè)出版社,2009年.[4]于淵.自己動手寫操作系統(tǒng).北京:電子工業(yè)出版社,2005年.[5]StephenPrata.CPrimerPlus(第6版)(中文版).北京:人民郵電出版社,2016年.[6]鄧志.x86/x64體系探索及編程.北京:電子工業(yè)出版社,2005年.[7]藍(lán)楓葉.自己動手寫嵌入式操作系統(tǒng).北京:電子工業(yè)出版社,2007年[8]趙炯.Linux內(nèi)核完全注釋.北京:機(jī)械工業(yè)出版社,2005年致謝畢業(yè)設(shè)計接近了尾聲,當(dāng)我完成這個畢業(yè)設(shè)計論文的時候,如釋重負(fù)。首先,我要感謝我的指導(dǎo)老師張東輝老師,在整個過程中老師給予了我極大地幫助,沒有老師的盡心指導(dǎo)我不可能完成此次畢業(yè)設(shè)計。在我做畢業(yè)設(shè)計的幾個月里,從選題到設(shè)計等各個環(huán)節(jié)中都給予了我悉心的指導(dǎo),在此謹(jǐn)向張老師致以誠摯的謝意和崇高的敬意。同時也向?qū)ξ姨峁椭耐瑢W(xué)們表示感謝。經(jīng)過這次畢業(yè)設(shè)計,將整個大學(xué)生涯的知識鞏固了一遍,提高了自己的應(yīng)用能力和開發(fā)能力。在此我要再此向所有幫助我和支持我的老師,同學(xué)表示深深的感謝。附錄#include"fs.h"#include"super_block.h"#include"inode.h"#include"dir.h"#include"stdint.h"#include"stdio-kernel.h"#include"list.h"#include"string.h"#include"ide.h"#include"global.h"#include"debug.h"#include"memory.h"#include"file.h"#include"console.h"#include"keyboard.h"#include"ioqueue.h"#include"pipe.h"structpartition*cur_part; //默認(rèn)情況下操作的是哪個分區(qū)/*在分區(qū)鏈表中找到名為part_name的分區(qū),并將其指針賦值給cur_part*/staticboolmount_partition(structlist_elem*pelem,intarg){char*part_name=(char*)arg;structpartition*part=elem2entry(structpartition,part_tag,pelem);if(!strcmp(part->name,part_name)){cur_part=part;structdisk*hd=cur_part->my_disk;/*sb_buf用來存儲從硬盤上讀入的超級塊*/structsuper_block*sb_buf=(structsuper_block*)sys_malloc(SECTOR_SIZE);/*在內(nèi)存中創(chuàng)建分區(qū)cur_part的超級塊*/cur_part->sb=(structsuper_block*)sys_malloc(sizeof(structsuper_block));if(cur_part->sb==NULL){ PANIC("allocmemoryfailed!");}/*讀入超級塊*/memset(sb_buf,0,SECTOR_SIZE);ide_read(hd,cur_part->start_lba+1,sb_buf,1);/*把sb_buf中超級塊的信息復(fù)制到分區(qū)的超級塊sb中。*/memcpy(cur_part->sb,sb_buf,sizeof(structsuper_block));/**********將硬盤上的塊位圖讀入到內(nèi)存****************/cur_part->block_bitmap.bits=(uint8_t*)sys_malloc(sb_buf->block_bitmap_sects*SECTOR_SIZE);if(cur_part->block_bitmap.bits==NULL){ PANIC("allocmemoryfailed!");}cur_part->block_bitmap.btmp_bytes_len=sb_buf->block_bitmap_sects*SECTOR_SIZE;/*從硬盤上讀入塊位圖到分區(qū)的block_bitmap.bits*/ide_read(hd,sb_buf->block_bitmap_lba,cur_part->block_bitmap.bits,sb_buf->block_bitmap_sects);/*************************************************************//**********將硬盤上的inode位圖讀入到內(nèi)存************/cur_part->inode_bitmap.bits=(uint8_t*)sys_malloc(sb_buf->inode_bitmap_sects*SECTOR_SIZE);if(cur_part->inode_bitmap.bits==NULL){ PANIC("allocmemoryfailed!");}cur_part->inode_bitmap.btmp_bytes_len=sb_buf->inode_bitmap_sects*SECTOR_SIZE;/*從硬盤上讀入inode位圖到分區(qū)的inode_bitmap.bits*/ide_read(hd,sb_buf->inode_bitmap_lba,cur_part->inode_bitmap.bits,sb_buf->inode_bitmap_sects);/*************************************************************/list_init(&cur_part->open_inodes);printk("mount%sdone!\n",part->name);/*此處返回true是為了迎合主調(diào)函數(shù)list_traversal的實現(xiàn),與函數(shù)本身功能無關(guān)。只有返回true時list_traversal才會停止遍歷,減少了后面元素?zé)o意義的遍歷.*/returntrue;}returnfalse;//使list_traversal繼續(xù)遍歷}/*格式化分區(qū),也就是初始化分區(qū)的元信息,創(chuàng)建文件系統(tǒng)*/staticvoidpartition_format(structpartition*part){/*為方便實現(xiàn),一個塊大小是一扇區(qū)*/uint32_tboot_sector_sects=1; uint32_tsuper_block_sects=1;uint32_tinode_bitmap_sects=DIV_ROUND_UP(MAX_FILES_PER_PART,BITS_PER_SECTOR); //I結(jié)點位圖占用的扇區(qū)數(shù).最多支持4096個文件uint32_tinode_table_sects=DIV_ROUND_UP(((sizeof(structinode)*MAX_FILES_PER_PART)),SECTOR_SIZE);uint32_tused_sects=boot_sector_sects+super_block_sects+inode_bitmap_sects+inode_table_sects;uint32_tfree_sects=part->sec_cnt-used_sects;/**************簡單處理塊位圖占據(jù)的扇區(qū)數(shù)***************/uint32_tblock_bitmap_sects;block_bitmap_sects=DIV_ROUND_UP(free_sects,BITS_PER_SECTOR);/*block_bitmap_bit_len是位圖中位的長度,也是可用塊的數(shù)量*/uint32_tblock_bitmap_bit_len=free_sects-block_bitmap_sects;block_bitmap_sects=DIV_ROUND_UP(block_bitmap_bit_len,BITS_PER_SECTOR);/*********************************************************//*超級塊初始化*/structsuper_blocksb;sb.magic=0x19590318;sb.sec_cnt=part->sec_cnt;sb.inode_cnt=MAX_FILES_PER_PART;sb.part_lba_base=part->start_lba;sb.block_bitmap_lba=sb.part_lba_base+2; //第0塊是引導(dǎo)塊,第1塊是超級塊sb.block_bitmap_sects=block_bitmap_sects;sb.inode_bitmap_lba=sb.block_bitmap_lba+sb.block_bitmap_sects;sb.inode_bitmap_sects=inode_bitmap_sects;sb.inode_table_lba=sb.inode_bitmap_lba+sb.inode_bitmap_sects;sb.inode_table_sects=inode_table_sects;sb.data_start_lba=sb.inode_table_lba+sb.inode_table_sects;sb.root_inode_no=0;sb.dir_entry_size=sizeof(structdir_entry);printk("%sinfo:\n",part->name);printk("magic:0x%x\npart_lba_base:0x%x\nall_sectors:0x%x\ninode_cnt:0x%x\nblock_bitmap_lba:0x%x\nblock_bitmap_sectors:0x%x\ninode_bitmap_lba:0x%x\ninode_bitmap_sectors:0x%x\ninode_table_lba:0x%x\ninode_table_sectors:0x%x\ndata_start_lba:0x%x\n",sb.magic,sb.part_lba_base,sb.sec_cnt,sb.inode_cnt,sb.block_bitmap_lba,sb.block_bitmap_sects,sb.inode_bitmap_lba,sb.inode_bitmap_sects,sb.inode_table_lba,sb.inode_table_sects,sb.data_start_lba);structdisk*hd=part->my_disk;/********************************1將超級塊寫入本分區(qū)的1扇區(qū)*******************************/ide_write(hd,part->start_lba+1,&sb,1);printk("super_block_lba:0x%x\n",part->start_lba+1);/*找出數(shù)據(jù)量最大的元信息,用其尺寸做存儲緩沖區(qū)*/uint32_tbuf_size=(sb.block_bitmap_sects>=sb.inode_bitmap_sects?sb.block_bitmap_sects:sb.inode_bitmap_sects);buf_size=(buf_size>=sb.inode_table_sects?buf_size:sb.inode_table_sects)*SECTOR_SIZE;uint8_t*buf=(uint8_t*)sys_malloc(buf_size); //申請的內(nèi)存由內(nèi)存管理系統(tǒng)清0后返回/***************************************2將塊位圖初始化并寫入sb.block_bitmap_lba**************************************//*初始化塊位圖block_bitmap*/buf[0]|=0x01;//第0個塊預(yù)留給根目錄,位圖中先占位uint32_tblock_bitmap_last_byte=block_bitmap_bit_len/8;uint8_tblock_bitmap_last_bit=block_bitmap_bit_len%8;uint32_tlast_size=SECTOR_SIZE-(block_bitmap_last_byte%SECTOR_SIZE); //last_size是位圖所在最后一個扇區(qū)中,不足一扇區(qū)的其余部分/*1先將位圖最后一字節(jié)到其所在的扇區(qū)的結(jié)束全置為1,即超出實際塊數(shù)的部分直接置為已占用*/memset(&buf[block_bitmap_last_byte],0xff,last_size);/*2再將上一步中覆蓋的最后一字節(jié)內(nèi)的有效位重新置0*/uint8_tbit_idx=0;while(bit_idx<=block_bitmap_last_bit){buf[block_bitmap_last_byte]&=~(1<<bit_idx++);}ide_write(hd,sb.block_bitmap_lba,buf,sb.block_bitmap_sects);/****************************************3將inode位圖初始化并寫入sb.inode_bitmap_lba****************************************//*先清空緩沖區(qū)*/memset(buf,0,buf_size);buf[0]|=0x1;//第0個inode分給了根目錄/*由于inode_table中共4096個inode,位圖inode_bitmap正好占用1扇區(qū),*即inode_bitmap_sects等于1,所以位圖中的位全都代表inode_table中的inode,*無須再像block_bitmap那樣單獨處理最后一扇區(qū)的剩余部分,*inode_bitmap所在的扇區(qū)中沒有多余的無效位*/ide_write(hd,sb.inode_bitmap_lba,buf,sb.inode_bitmap_sects);/****************************************4將inode數(shù)組初始化并寫入sb.inode_table_lba****************************************//*準(zhǔn)備寫inode_table中的第0項,即根目錄所在的inode*/memset(buf,0,buf_size);//先清空緩沖區(qū)bufstructinode*i=(structinode*)buf;i->i_size=sb.dir_entry_size*2; //.和..i->i_no=0;//根目錄占inode數(shù)組中第0個inodei->i_sectors[0]=sb.data_start_lba; //由于上面的memset,i_sectors數(shù)組的其它元素都初始化為0ide_write(hd,sb.inode_table_lba,buf,sb.inode_table_sects);/****************************************5將根目錄初始化并寫入sb.data_start_lba***************************************//*寫入根目錄的兩個目錄項.和..*/memset(buf,0,buf_size);structdir_entry*p_de=(structdir_entry*)buf;/*初始化當(dāng)前目錄"."*/memcpy(p_de->filename,".",1);p_de->i_no=0;p_de->f_type=FT_DIRECTORY;p_de++;/*初始化當(dāng)前目錄父目錄".."*/memcpy(p_de->filename,"..",2);p_de->i_no=0;//根目錄的父目錄依然是根目錄自己p_de->f_type=FT_DIRECTORY;/*sb.data_start_lba已經(jīng)分配給了根目錄,里面是根目錄的目錄項*/ide_write(hd,sb.data_start_lba,buf,1);printk("root_dir_lba:0x%x\n",sb.data_start_lba);printk("%sformatdone\n",part->name);sys_free(buf);}/*將最上層路徑名稱解析出來*/char*path_parse(char*pathname,char*name_store){if(pathname[0]=='/'){//根目錄不需要單獨解析/*路徑中出現(xiàn)1個或多個連續(xù)的字符'/',將這些'/'跳過,如"http:///a/b"*/while(*(++pathname)=='/');}/*開始一般的路徑解析*/while(*pathname!='/'&&*pathname!=0){*name_store++=*pathname++;}if(pathname[0]==0){//若路徑字符串為空則返回NULLreturnNULL;}returnpathname;}/*返回路徑深度,比如/a/b/c,深度為3*/int32_tpath_depth_cnt(char*pathname){ASSERT(pathname!=NULL);char*p=pathname;charname[MAX_FILE_NAME_LEN];//用于path_parse的參數(shù)做路徑解析uint32_tdepth=0;/*解析路徑,從中拆分出各級名稱*/p=path_parse(p,name);while(name[0]){depth++;memset(name,0,MAX_FILE_NAME_LEN);if(p){ //如果p不等于NULL,繼續(xù)分析路徑 p=path_parse(p,name);}}returndepth;}/*搜索文件pathname,若找到則返回其inode號,否則返回-1*/staticintsearch_file(constchar*pathname,structpath_search_record*searched_record){/*如果待查找的是根目錄,為避免下面無用的查找,直接返回已知根目錄信息*/if(!strcmp(pathname,"/")||!strcmp(pathname,"/.")||!strcmp(pathname,"/..")){searched_record->parent_dir=&root_dir;searched_record->file_type=FT_DIRECTORY;searched_record->searched_path[0]=0; //搜索路徑置空return0;}uint32_tpath_len=strlen(pathname);/*保證pathname至少是這樣的路徑/x且小于最大長度*/ASSERT(pathname[0]=='/'&&path_len>1&&path_len<MAX_PATH_LEN);char*sub_path=(char*)pathname;structdir*parent_dir=&root_dir; structdir_entrydir_e;/*記錄路徑解析出來的各級名稱,如路徑"/a/b/c",*數(shù)組name每次的值分別是"a","b","c"*/charname[MAX_FILE_NAME_LEN]={0};s

溫馨提示

  • 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論