《簡(jiǎn)單文件系統(tǒng)的實(shí)現(xiàn).doc》由會(huì)員分享,可在線閱讀,更多相關(guān)《簡(jiǎn)單文件系統(tǒng)的實(shí)現(xiàn).doc(16頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
第三章 簡(jiǎn)單文件系統(tǒng)的實(shí)現(xiàn)
3.1 設(shè)計(jì)目的和內(nèi)容要求
1. 設(shè)計(jì)目的
通過(guò)具體的文件存儲(chǔ)空間的管理、文件的物理結(jié)構(gòu)、目錄結(jié)構(gòu)和文件操作的實(shí)現(xiàn),加深對(duì)文件系統(tǒng)內(nèi)部數(shù)據(jù)結(jié)構(gòu)、功能以及實(shí)現(xiàn)過(guò)程的理解。
2.內(nèi)容要求
(1) 在內(nèi)存中開(kāi)辟一個(gè)虛擬磁盤(pán)空間作為文件存儲(chǔ)分區(qū),在其上實(shí)現(xiàn)一個(gè)簡(jiǎn)單的基于多級(jí)目錄的單用戶(hù)單任務(wù)系統(tǒng)中的文件系統(tǒng)。在退出該文件系統(tǒng)的使用時(shí),應(yīng)將該虛擬文件系統(tǒng)以一個(gè)Windows 文件的方式保存到磁盤(pán)上,以便下次可以再將它恢復(fù)到內(nèi)存的虛擬磁盤(pán)空間中。
(2) 文件存儲(chǔ)空間的分配可采用顯式鏈接分配或其他的辦法。
(3) 空閑磁盤(pán)空間的管理可選擇位示圖或其他的辦法。如果采用位示圖來(lái)管理文件存儲(chǔ)空間,并采用顯式鏈接分配方式,那么可以將位示圖合并到FAT中。
(4) 文件目錄結(jié)構(gòu)采用多級(jí)目錄結(jié)構(gòu)。為了簡(jiǎn)單起見(jiàn),可以不使用索引結(jié)點(diǎn),其中的每個(gè)目錄項(xiàng)應(yīng)包含文件名、物理地址、長(zhǎng)度等信息,還可以通過(guò)目錄項(xiàng)實(shí)現(xiàn)對(duì)文件的讀和寫(xiě)的保護(hù)。
(5) 要求提供以下操作命令:
l my_format:對(duì)文件存儲(chǔ)器進(jìn)行格式化,即按照文件系統(tǒng)的結(jié)構(gòu)對(duì)虛擬磁盤(pán)空間進(jìn)行布局,并在其上創(chuàng)建根目錄以及用于管理文件存儲(chǔ)空間等的數(shù)據(jù)結(jié)構(gòu)。
l my_mkdir:用于創(chuàng)建子目錄。
l my_rmdir:用于刪除子目錄。
l my_ls:用于顯示目錄中的內(nèi)容。
l my_cd:用于更改當(dāng)前目錄。
l my_create:用于創(chuàng)建文件。
l my_open:用于打開(kāi)文件。
l my_close:用于關(guān)閉文件。
l my_write:用于寫(xiě)文件。
l my_read:用于讀文件。
l my_rm:用于刪除文件。
l my_exitsys:用于退出文件系統(tǒng)。
3.學(xué)時(shí)安排
授課2學(xué)時(shí),上機(jī)9學(xué)時(shí)。
4. 開(kāi)發(fā)平臺(tái)
C或C++均可。
5.思考
(1) 我們的數(shù)據(jù)結(jié)構(gòu)中的文件物理地址信息是使用C語(yǔ)言的指針類(lèi)型、還是整型,為什么?
(2) 如果引入磁盤(pán)索引結(jié)點(diǎn),上述實(shí)現(xiàn)過(guò)程需要作哪些修改?
(3) 如果設(shè)計(jì)的是一個(gè)單用戶(hù)多任務(wù)文件系統(tǒng),則系統(tǒng)需要進(jìn)行哪些擴(kuò)充(尤其要考慮讀寫(xiě)指針問(wèn)題)?如果設(shè)計(jì)的是一個(gè)多用戶(hù)文件系統(tǒng),則又要進(jìn)行哪些擴(kuò)充?
3.2 預(yù)備知識(shí)
3.2.1 FAT文件系統(tǒng)介紹
1.概述
FAT文件系統(tǒng)是微軟公司在其早期的操作系統(tǒng)MS-DOS及Windows9x中采用的文件系統(tǒng),它被設(shè)計(jì)用來(lái)管理小容量的磁盤(pán)空間。FAT文件系統(tǒng)是以他的文件組織方式——文件分配表(file allocation table,F(xiàn)AT)命名的,文件分配表的每個(gè)表項(xiàng)中存放某文件的下一個(gè)盤(pán)塊號(hào),而該文件的起始盤(pán)塊號(hào)則保存在它的文件控制塊FCB中。在文件分配表中,一般用FFFF來(lái)標(biāo)識(shí)文件的結(jié)束;用0000來(lái)標(biāo)識(shí)某個(gè)邏輯塊未被分配,即是空閑塊。為了提高文件系統(tǒng)的可靠性,在邏輯磁盤(pán)上通常設(shè)置兩張文件分配表,它們互為備份。此外,文件分配表必須存放在邏輯磁盤(pán)上的固定位置,而根目錄區(qū)通常位于FAT2之后,以便操作系統(tǒng)在啟動(dòng)時(shí)能夠定位所需的文件,其磁盤(pán)布局如圖3-1所示:
圖3-1 FAT文件系統(tǒng)磁盤(pán)布局
上述磁盤(pán)布局中,引導(dǎo)塊中主要存放了用于描述分區(qū)的各種信息,包括邏輯塊的大小、文件分配表的大小及位置、根目錄的大小及位置等。除此之外,用于加載操作系統(tǒng)內(nèi)核的引導(dǎo)程序也存儲(chǔ)在引導(dǎo)塊中。
FAT文件系統(tǒng)家族又分為FAT12、FAT16、FAT32三種類(lèi)型,這里的數(shù)字表示文件分配表中每個(gè)表項(xiàng)(即簇號(hào))所占的位數(shù),即FAT12中每個(gè)表項(xiàng)占1.5個(gè)字節(jié)(12位),F(xiàn)AT16中每個(gè)表項(xiàng)占2個(gè)字節(jié)(16位),F(xiàn)AT32中每個(gè)表項(xiàng)占4個(gè)字節(jié)(32位)。由于FAT文件系統(tǒng)是以簇為單位為文件分配磁盤(pán)空間的(一個(gè)簇是一組連續(xù)的扇區(qū),通常包含2n個(gè)扇區(qū)),因此,F(xiàn)AT32比FAT12和FAT16支持更多的簇?cái)?shù)、更小的簇大小和更大的磁盤(pán)容量,從而大大提高磁盤(pán)空間的利用率。通常,F(xiàn)AT12適用于小容量磁盤(pán),如軟盤(pán);FAT16是MS-DOS的文件系統(tǒng);FAT32是Windows9x中的主要文件系統(tǒng),開(kāi)始支持大容量磁盤(pán)。
2.文件控制塊FCB
為了正確、方便地操作文件,必須設(shè)置相應(yīng)的數(shù)據(jù)結(jié)構(gòu)用于存放文件的描述和控制信息,常用的數(shù)據(jù)結(jié)構(gòu)有文件控制塊(簡(jiǎn)稱(chēng)FCB)和索引節(jié)點(diǎn)(簡(jiǎn)稱(chēng)i節(jié)點(diǎn))。在FAT文件系統(tǒng)中使用文件控制塊。文件與文件控制塊一一對(duì)應(yīng),而文件控制塊的有序集合就稱(chēng)為文件目錄,即一個(gè)文件控制塊就是一個(gè)文件目錄項(xiàng)。
雖然不同文件系統(tǒng)的文件控制塊的內(nèi)容和格式不完全相同,但通常都包括以下三類(lèi)信息:基本信息、存取控制信息和使用信息。
(1)基本信息。包括文件名、用戶(hù)名、文件類(lèi)型、文件的物理地址、文件長(zhǎng)度、文件的邏輯結(jié)構(gòu)和物理結(jié)構(gòu)等。
(2)存取控制信息。一般分別給出文件主、伙伴用戶(hù)、一般用戶(hù)的存取權(quán)限。
(3)使用信息。包括文件的建立日期及時(shí)間、上次存取文件的日期及時(shí)間、當(dāng)前的使用信息等。
以MS-DOS(使用FAT16文件系統(tǒng))為例,它的每個(gè)文件控制塊包括32個(gè)字節(jié),其字節(jié)分配情況如圖3-2所示:
圖3-2 MS-DOS的文件控制塊
其中屬性字段占一個(gè)字節(jié),它的每一位用來(lái)表示該文件是否具有某種屬性,如果某一位的值為1,則表示該文件具有該屬性。各位所表示的屬性如表3-1所示:
表3-1 文件屬性對(duì)照表
位
7
6
5
4
3
2
1
0
屬性
保留
保留
存檔
子目錄
卷標(biāo)
系統(tǒng)文件
隱藏
只讀
3.根目錄區(qū)
FAT12、FAT16的根目錄區(qū)是固定區(qū)域、固定大小的,位于第二個(gè)FAT之后,如圖3-1所示,且占據(jù)若干連續(xù)扇區(qū),其中FAT12占14個(gè)扇區(qū),一共224個(gè)根目錄項(xiàng);而FAT16占32個(gè)扇區(qū),最多保存512個(gè)目錄項(xiàng),作為系統(tǒng)區(qū)的一部分。FAT32的根目錄是作為文件處理的,采用與子目錄文件相同的管理方式,其位置不是固定的,不過(guò)一般情況也是位于第二個(gè)FAT之后的,其大小可視需要增加,因此根目錄下的文件數(shù)目不再受最多512個(gè)的限制。
3.2.2 幾個(gè)C語(yǔ)言庫(kù)函數(shù)介紹
由于我們的文件系統(tǒng)是建立在內(nèi)存的虛擬磁盤(pán)上的,在退出文件系統(tǒng)的時(shí)候必須以一個(gè)文件的形式保存到磁盤(pán)上;而在啟動(dòng)文件系統(tǒng)的時(shí)候必須從磁盤(pán)上將該文件讀入到內(nèi)存的虛擬磁盤(pán)中。下面介紹幾個(gè)可能會(huì)用到的C庫(kù)函數(shù),在使用這些庫(kù)函數(shù)之前必須包含頭文件“stdio.h”。
1.打開(kāi)文件函數(shù)fopen()
(1)格式:FILE *fopen(const char *filename,const char *mode)
(2)功能:按照指定打開(kāi)方式打開(kāi)指定文件。
(3)輸入?yún)?shù)說(shuō)明:
filename:待打開(kāi)的文件名,如果不存在就創(chuàng)建該文件。
mode: 文件打開(kāi)方式,常用的有:
l "r":為讀而打開(kāi)文本文件(不存在則出錯(cuò))。
l "w":為寫(xiě)而打開(kāi)文本文件(若不存在則創(chuàng)建該文件;反之,則從文件起始位置寫(xiě),原內(nèi)容將被覆蓋)。
l "a":為在文件末尾添加數(shù)據(jù)而打開(kāi)文本文件。(若不存在則創(chuàng)建該文件;反之,在原文件末尾追加)。
l "r+":為讀和寫(xiě)而打開(kāi)文本文件。(讀時(shí),從頭開(kāi)始;在寫(xiě)數(shù)據(jù)時(shí),新數(shù)據(jù)只覆蓋所占的空間,其后不變) 。
l "w+":首先建立一個(gè)新文件,進(jìn)行寫(xiě)操作,隨后可以從頭開(kāi)始讀。(若文件存在,原內(nèi)容將全部消失) 。
l "a+":功能與"a"相同;只是在文件末尾添加新的數(shù)據(jù)后,可以從頭開(kāi)始讀。
另外,上述模式字符串中都可以加一個(gè)“b”字符,如rb、wb、ab、rb+、wb+、ab+等組合,字符“b”表示fopen() 函數(shù)打開(kāi)的文件為二進(jìn)制文件,而非純文字文件。
(4)輸出:一個(gè)指向FILE類(lèi)型的指針。
2.關(guān)閉文件函數(shù)fclose()
(1)格式:int fclose(FILE * stream);
(2)功能:用來(lái)關(guān)閉先前fopen()打開(kāi)的一個(gè)文件。此動(dòng)作會(huì)讓緩沖區(qū)內(nèi)的數(shù)據(jù)寫(xiě)入文件中,并釋放系統(tǒng)所提供的文件資源。
(3)輸入?yún)?shù)說(shuō)明:
stream:指向要關(guān)閉文件的指針,它是先前執(zhí)行fopen()函數(shù)的返回值。
(4)輸出:若關(guān)閉文件成功則返回0;有錯(cuò)誤發(fā)生時(shí)則返回EOF并把錯(cuò)誤代碼存到errno。
3.讀文件函數(shù)fread()
(1)格式:size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
(2)功能:讀二進(jìn)制文件到內(nèi)存。
(3)輸入?yún)?shù)說(shuō)明:
buffer:用于存放輸入數(shù)據(jù)的緩沖區(qū)的首地址;
stream:使用fopen()打開(kāi)的文件的指針,用于指示要讀取的文件;
size: 每個(gè)數(shù)據(jù)塊的字節(jié)數(shù);
count: 要讀入的數(shù)據(jù)塊的個(gè)數(shù);
size*count:表示要求讀取的字節(jié)數(shù)。
(4)輸出:實(shí)際讀取的數(shù)據(jù)塊的個(gè)數(shù)。
4.寫(xiě)文件函數(shù)fwrite()
(1)格式:size_t fwite(const void *buffer,size_t size,size_t count,FILE *stream);
(2)功能:將數(shù)據(jù)寫(xiě)到二進(jìn)制文件中。
(3)輸入?yún)?shù)說(shuō)明:
buffer:用于存放輸出數(shù)據(jù)的緩沖區(qū)的首地址;
stream:使用fopen()打開(kāi)的文件的指針,用于指示要寫(xiě)出的文件;
size: 每個(gè)數(shù)據(jù)塊的字節(jié)數(shù);
count: 要寫(xiě)出的數(shù)據(jù)塊的個(gè)數(shù);
size*count:表示要求寫(xiě)出的字符數(shù)。
(4)輸出:實(shí)際寫(xiě)出的數(shù)據(jù)塊的個(gè)數(shù)。
5.判斷文件結(jié)束函數(shù)feof ()
(1)格式:int feof(FILE * stream)
(2)功能:用來(lái)判斷是否已讀取到文件末尾。
(3)輸入?yún)?shù)說(shuō)明:
stream:使用fopen()打開(kāi)的文件的指針,用于指示要判斷的文件。
(4)輸出:如果已讀到文件尾則返回非零值,其他情況返回0。
6.定位文件函數(shù)fseek()
(1)格式:int fseek( FILE *stream, long offset, int origin );
(2)功能: 移動(dòng)文件讀寫(xiě)指針在文件中的位置。
(3)輸入?yún)?shù)說(shuō)明:
stream:使用fopen()打開(kāi)的文件的指針,用于指示要定位讀寫(xiě)指針的文件;
offset:位移量,以字節(jié)為單位;
origin:初始位置,有三個(gè)常量:
SEEK_CUR:讀寫(xiě)指針當(dāng)前位置;
SEEK_SET:文件開(kāi)頭;
SEEK_END:文件末尾。
當(dāng)origin值為SEEK_CUR 或SEEK_END時(shí),參數(shù)offset可以為負(fù)值。
3.3實(shí)例系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
本實(shí)例系統(tǒng)是仿照FAT16文件系統(tǒng)來(lái)設(shè)計(jì)實(shí)現(xiàn)的,但根目錄沒(méi)有采用FAT16的固定位置、固定大小的根目錄區(qū),而是以根目錄文件的形式來(lái)實(shí)現(xiàn)的,這也是目前主流文件系統(tǒng)對(duì)根目錄的處理方式。
3.3.1 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
1.需要包含的頭文件
(1)#include
(2)#include
(3)#include
(4)#include
2.定義的常量
(1)#define BLOCKSIZE 1024 磁盤(pán)塊大小
(2)#define SIZE 1024000 虛擬磁盤(pán)空間大小
(3)#define END 65535 FAT中的文件結(jié)束標(biāo)志
(4)#define FREE 0 FAT中盤(pán)塊空閑標(biāo)志
(5)#define ROOTBLOCKNUM 2 根目錄區(qū)所占盤(pán)塊總數(shù)
(6)#define MAXOPENFILE 10 最多同時(shí)打開(kāi)文件個(gè)數(shù)
3.?dāng)?shù)據(jù)結(jié)構(gòu)
(1)文件控制塊FCB
用于記錄文件的描述和控制信息,每個(gè)文件設(shè)置一個(gè)FCB,它也是文件的目錄項(xiàng)的內(nèi)容。
typedef struct FCB //仿照FAT16設(shè)置的
{
char filename[8]; //文件名
char exname[3];//文件擴(kuò)展名
unsigned char attribute;//文件屬性字段:為簡(jiǎn)單起見(jiàn),我們只為文件設(shè)置了兩種屬性:
//值為0時(shí)表示目錄文件,值為1時(shí)表示數(shù)據(jù)文件
unsigned short time;//文件創(chuàng)建時(shí)間
unsigned short data;//文件創(chuàng)建日期
unsigned short first;//文件起始盤(pán)塊號(hào)
unsigned long length;//文件長(zhǎng)度(字節(jié)數(shù))
char free;//表示目錄項(xiàng)是否為空,若值為0,表示空,值為1,表示已分配
}fcb;
(2)文件分配表FAT
在本實(shí)例中,文件分配表有兩個(gè)作用:一是記錄磁盤(pán)上每個(gè)文件所占據(jù)的磁盤(pán)塊的塊號(hào);二是記錄磁盤(pán)上哪些塊已經(jīng)分配出去了,哪些塊是空閑的,即起到了位示圖的作用。若FAT中某個(gè)表項(xiàng)的值為FREE,則表示該表項(xiàng)所對(duì)應(yīng)的磁盤(pán)塊是空閑的;若某個(gè)表項(xiàng)的值為END,則表示所對(duì)應(yīng)的磁盤(pán)塊是某文件的最后一個(gè)磁盤(pán)塊;若某個(gè)表項(xiàng)的值是其他值,則該值表示某文件的下一個(gè)磁盤(pán)塊的塊號(hào)。為了提高系統(tǒng)的可靠性,本實(shí)例中設(shè)置了兩張F(tuán)AT表,它們互為備份,每個(gè)FAT占據(jù)兩個(gè)磁盤(pán)塊。
typedef struct FAT
{
unsigned short id;
}fat;
(3)用戶(hù)打開(kāi)文件表USEROPEN
當(dāng)打開(kāi)一個(gè)文件時(shí),必須將文件的目錄項(xiàng)中的所有內(nèi)容全部復(fù)制到內(nèi)存中,同時(shí)還要記錄有關(guān)文件操作的動(dòng)態(tài)信息,如讀寫(xiě)指針的值等。在本實(shí)例中實(shí)現(xiàn)的是一個(gè)用于單用戶(hù)單任務(wù)系統(tǒng)的文件系統(tǒng),為簡(jiǎn)單起見(jiàn),我們把用戶(hù)文件描述符表和內(nèi)存FCB表合在一起,稱(chēng)為用戶(hù)打開(kāi)文件表,表項(xiàng)數(shù)目為10,即一個(gè)用戶(hù)最多可同時(shí)打開(kāi)10個(gè)文件。然后用一個(gè)數(shù)組來(lái)描述,則數(shù)組下標(biāo)即某個(gè)打開(kāi)文件的描述符。另外,我們?cè)谟脩?hù)打開(kāi)文件表中還設(shè)置了一個(gè)字段“char dir[80]”,用來(lái)記錄每個(gè)打開(kāi)文件所在的目錄名,以方便用戶(hù)打開(kāi)不同目錄下具有相同文件名的不同文件。
typedef struct USEROPEN
{
char filename[8]; //文件名
char exname[3];//文件擴(kuò)展名
unsigned char attribute;//文件屬性:值為0時(shí)表示目錄文件,值為1時(shí)表示數(shù)據(jù)文件
unsigned short time;//文件創(chuàng)建時(shí)間
unsigned short data;//文件創(chuàng)建日期
unsigned short first;//文件起始盤(pán)塊號(hào)
unsigned long length;//文件長(zhǎng)度(對(duì)數(shù)據(jù)文件是字節(jié)數(shù),對(duì)目錄文件可以是目錄項(xiàng)個(gè)數(shù))
char free;//表示目錄項(xiàng)是否為空,若值為0,表示空,值為1,表示已分配
//前面內(nèi)容是文件的FCB中的內(nèi)容。
// 下面設(shè)置的dirno和diroff記錄了相應(yīng)打開(kāi)文件的目錄項(xiàng)在父目錄文件中的位置,//這樣如果該文件的fcb被修改了,則要寫(xiě)回父目錄文件時(shí)比較方便
int dirno; //相應(yīng)打開(kāi)文件的目錄項(xiàng)在父目錄文件中的盤(pán)塊號(hào)
int diroff;// 相應(yīng)打開(kāi)文件的目錄項(xiàng)在父目錄文件的dirno盤(pán)塊中的目錄項(xiàng)序號(hào)
char dir[MAXOPENFILE][80]; //相應(yīng)打開(kāi)文件所在的目錄名,這樣方便快速檢查出
//指定文件是否已經(jīng)打開(kāi)
int count; //讀寫(xiě)指針在文件中的位置
char fcbstate; //是否修改了文件的FCB的內(nèi)容,如果修改了置為1,否則為0
char topenfile; //表示該用戶(hù)打開(kāi)表項(xiàng)是否為空,若值為0,表示為空,否則表示已
//被某打開(kāi)文件占據(jù)
}useropen;
(4)引導(dǎo)塊BLOCK0
在引導(dǎo)塊中主要存放邏輯磁盤(pán)的相關(guān)描述信息,比如磁盤(pán)塊大小、磁盤(pán)塊數(shù)量、文件分配表、根目錄區(qū)、數(shù)據(jù)區(qū)在磁盤(pán)上的起始位置等。如果是引導(dǎo)盤(pán),還要存放操作系統(tǒng)的引導(dǎo)信息。本實(shí)例是在內(nèi)存的虛擬磁盤(pán)中創(chuàng)建一個(gè)文件系統(tǒng),因此所包含的內(nèi)容比較少,只有磁盤(pán)塊大小、磁盤(pán)塊數(shù)量、數(shù)據(jù)區(qū)開(kāi)始位置、根目錄文件開(kāi)始位置等。
typedef struct BLOCK0 //引導(dǎo)塊內(nèi)容
{
//存儲(chǔ)一些描述信息,如磁盤(pán)塊大小、磁盤(pán)塊數(shù)量、最多打開(kāi)文件數(shù)等、
char information[200];
unsigned short root; //根目錄文件的起始盤(pán)塊號(hào)
unsigned char *startblock; //虛擬磁盤(pán)上數(shù)據(jù)區(qū)開(kāi)始位置
}block0;
4.全局變量定義
(1)unsigned char *myvhard: 指向虛擬磁盤(pán)的起始地址
(2)useropen openfilelist[MAXOPENFILE]: 用戶(hù)打開(kāi)文件表數(shù)組
(3)useropen *ptrcurdir: 指向用戶(hù)打開(kāi)文件表中的當(dāng)前目錄所在打開(kāi)文件表項(xiàng)的位置;
(4)char currentdir[80]: 記錄當(dāng)前目錄的目錄名(包括目錄的路徑)
(5)unsigned char* startp: 記錄虛擬磁盤(pán)上數(shù)據(jù)區(qū)開(kāi)始位置
5.虛擬磁盤(pán)空間布局
由于真正的磁盤(pán)操作需要涉及到設(shè)備的驅(qū)動(dòng)程序,所以本實(shí)例是在內(nèi)存中申請(qǐng)一塊空間作為虛擬磁盤(pán)使用,我們的文件系統(tǒng)就建立在這個(gè)虛擬磁盤(pán)上。虛擬磁盤(pán)一共劃分成1000個(gè)磁盤(pán)塊,每個(gè)塊1024個(gè)字節(jié),其布局格式是模仿FAT文件系統(tǒng)設(shè)計(jì)的,其中引導(dǎo)塊占一個(gè)盤(pán)塊,兩張F(tuán)AT各占2個(gè)盤(pán)塊,剩下的空間全部是數(shù)據(jù)區(qū),在對(duì)虛擬磁盤(pán)進(jìn)行格式化的時(shí)候,將把數(shù)據(jù)區(qū)第1塊(即虛擬磁盤(pán)的第6塊)分配給根目錄文件,如圖3-3所示:
圖3-3 虛擬磁盤(pán)空間布局
當(dāng)然,也可以仿照FAT16文件系統(tǒng),設(shè)置根目錄區(qū),其位置緊跟第2張F(tuán)AT后面,大小也是固定的,這個(gè)思路相對(duì)要簡(jiǎn)單一點(diǎn),請(qǐng)同學(xué)們自己去實(shí)現(xiàn)。
3.3.2 實(shí)例主要命令及函數(shù)設(shè)計(jì)
1.系統(tǒng)主函數(shù)main()
(1)對(duì)應(yīng)命令:無(wú)
(2)命令調(diào)用格式:無(wú)
(3)函數(shù)設(shè)計(jì)格式:void main()
(4)功能:系統(tǒng)主函數(shù)
(5)輸入:無(wú)
(6)輸出:無(wú)
(7)函數(shù)需完成的工作:
① 對(duì)前面定義的全局變量進(jìn)行初始化;
② 調(diào)用startsys()進(jìn)入文件系統(tǒng);
③ 列出文件系統(tǒng)提供的各項(xiàng)功能及命令調(diào)用格式;
④ 顯示命令行提示符,等待用戶(hù)輸入命令;
⑤ 將用戶(hù)輸入的命令保存到一個(gè)buf中;
⑥ 對(duì)buf中的內(nèi)容進(jìn)行命令解析,并調(diào)用相應(yīng)的函數(shù)執(zhí)行用戶(hù)鍵入的命令;
⑦ 如果命令不是“my_exitsys”,則命令執(zhí)行完畢后轉(zhuǎn)④。
2. 進(jìn)入文件系統(tǒng)函數(shù)startsys()
(1)對(duì)應(yīng)命令:無(wú)
(2)命令調(diào)用格式:無(wú)
(3)函數(shù)設(shè)計(jì)格式:void startsys()
(4)功能:由main()函數(shù)調(diào)用,進(jìn)入并初始化我們所建立的文件系統(tǒng),以供用戶(hù)使用。
(5)輸入:無(wú)
(6)輸出:無(wú)。
(7)函數(shù)需完成的工作:
① 申請(qǐng)?zhí)摂M磁盤(pán)空間;
② 使用c語(yǔ)言的庫(kù)函數(shù)fopen()打開(kāi)myfsys文件:若文件存在,則轉(zhuǎn)③;若文件不存在,則創(chuàng)建之,轉(zhuǎn)⑤
③ 使用c語(yǔ)言的庫(kù)函數(shù)fread()讀入myfsys文件內(nèi)容到用戶(hù)空間中的一個(gè)緩沖區(qū)中,并判斷其開(kāi)始的8個(gè)字節(jié)內(nèi)容是否為“10101010”(文件系統(tǒng)魔數(shù)),如果是,則轉(zhuǎn)④;否則轉(zhuǎn)⑤;
④ 將上述緩沖區(qū)中的內(nèi)容復(fù)制到內(nèi)存中的虛擬磁盤(pán)空間中;轉(zhuǎn)⑦
⑤ 在屏幕上顯示“myfsys文件系統(tǒng)不存在,現(xiàn)在開(kāi)始創(chuàng)建文件系統(tǒng)”信息,并調(diào)用my_format()對(duì)①中申請(qǐng)到的虛擬磁盤(pán)空間進(jìn)行格式化操作。轉(zhuǎn)⑥;
⑥ 將虛擬磁盤(pán)中的內(nèi)容保存到myfsys文件中;轉(zhuǎn)⑦
⑦ 使用c語(yǔ)言的庫(kù)函數(shù)fclose()關(guān)閉myfsys文件;
⑧ 初始化用戶(hù)打開(kāi)文件表,將表項(xiàng)0分配給根目錄文件使用,并填寫(xiě)根目錄文件的相關(guān)信息,由于根目錄沒(méi)有上級(jí)目錄,所以表項(xiàng)中的dirno和diroff分別置為5(根目錄所在起始?jí)K號(hào))和0;并將ptrcurdir指針指向該用戶(hù)打開(kāi)文件表項(xiàng)。
⑨ 將當(dāng)前目錄設(shè)置為根目錄。
3.磁盤(pán)格式化函數(shù)my_format()
(1)對(duì)應(yīng)命令:my_format
(2)命令調(diào)用格式:my_format
(3)函數(shù)設(shè)計(jì)格式:void my_format()
(4)功能:對(duì)虛擬磁盤(pán)進(jìn)行格式化,布局虛擬磁盤(pán),建立根目錄文件(或根目錄區(qū))。
(5)輸入:無(wú)
(6)輸出:無(wú)。
(7)函數(shù)需完成的工作:
① 將虛擬磁盤(pán)第一個(gè)塊作為引導(dǎo)塊,開(kāi)始的8個(gè)字節(jié)是文件系統(tǒng)的魔數(shù),記為“10101010”;在之后寫(xiě)入文件系統(tǒng)的描述信息,如FAT表大小及位置、根目錄大小及位置、盤(pán)塊大小、盤(pán)塊數(shù)量、數(shù)據(jù)區(qū)開(kāi)始位置等信息;
② 在引導(dǎo)塊后建立兩張完全一樣的FAT表,用于記錄文件所占據(jù)的磁盤(pán)塊及管理虛擬磁盤(pán)塊的分配,每個(gè)FAT占據(jù)兩個(gè)磁盤(pán)塊;對(duì)于每個(gè)FAT中,前面5個(gè)塊設(shè)置為已分配,后面995個(gè)塊設(shè)置為空閑;
③ 在第二張F(tuán)AT后創(chuàng)建根目錄文件root,將數(shù)據(jù)區(qū)的第1塊(即虛擬磁盤(pán)的第6塊)分配給根目錄文件,在該磁盤(pán)上創(chuàng)建兩個(gè)特殊的目錄項(xiàng):“.”和“..”,其內(nèi)容除了文件名不同之外,其他字段完全相同。
4.更改當(dāng)前目錄函數(shù)my_cd()
(1)對(duì)應(yīng)命令:my_cd
(2)命令調(diào)用格式:my_cd dirname
(3)函數(shù)設(shè)計(jì)格式:void my_cd(char *dirname)
(4)功能:改變當(dāng)前目錄到指定的名為dirname的目錄。
(5)輸入:
dirname:新的當(dāng)前目錄的目錄名;
(6)輸出:無(wú)
(7)函數(shù)需完成的工作:
① 調(diào)用my_open()打開(kāi)指定目錄名的父目錄文件,并調(diào)用do_read()讀入該父目錄文件內(nèi)容到內(nèi)存中;
② 在父目錄文件中檢查新的當(dāng)前目錄名是否存在,如果存在則轉(zhuǎn)③,否則返回,并顯示出錯(cuò)信息;
③ 調(diào)用my_close()關(guān)閉①中打開(kāi)的父目錄文件;
④ 調(diào)用my_close()關(guān)閉原當(dāng)前目錄文件;
⑤ 如果新的當(dāng)前目錄文件沒(méi)有打開(kāi),則打開(kāi)該目錄文件;并將ptrcurdir指向該打開(kāi)文件表項(xiàng);
⑥ 設(shè)置當(dāng)前目錄為該目錄。
5.創(chuàng)建子目錄函數(shù)my_mkdir()
(1)對(duì)應(yīng)命令:my_mkdir
(2)命令調(diào)用格式:my_ mkdir dirname
(3)函數(shù)設(shè)計(jì)格式:void my_mkdir(char *dirname)
(4)功能:在當(dāng)前目錄下創(chuàng)建名為dirname的子目錄。
(5)輸入:
dirname:新建目錄的目錄名。
(6)輸出:無(wú)。
(7)函數(shù)需完成的工作:
① 調(diào)用do_read()讀入當(dāng)前目錄文件內(nèi)容到內(nèi)存,檢查當(dāng)前目錄下新建目錄文件是否重名,若重名則返回,并顯示錯(cuò)誤信息;
② 為新建子目錄文件分配一個(gè)空閑打開(kāi)文件表項(xiàng),如果沒(méi)有空閑表項(xiàng)則返回-1,并顯示錯(cuò)誤信息;
③ 檢查FAT是否有空閑的盤(pán)塊,如有則為新建目錄文件分配一個(gè)盤(pán)塊,否則釋放①中分配的打開(kāi)文件表項(xiàng),返回,并顯示錯(cuò)誤信息;
④ 在當(dāng)前目錄中為新建目錄文件尋找一個(gè)空閑的目錄項(xiàng)或?yàn)槠渥芳右粋€(gè)新的目錄項(xiàng);需修改當(dāng)前目錄文件的長(zhǎng)度信息,并將當(dāng)前目錄文件的用戶(hù)打開(kāi)文件表項(xiàng)中的fcbstate置為1;
⑤ 準(zhǔn)備好新建目錄文件的FCB的內(nèi)容,文件的屬性為目錄文件,以覆蓋寫(xiě)方式調(diào)用do_write()將其填寫(xiě)到對(duì)應(yīng)的空目錄項(xiàng)中;
⑥ 在新建目錄文件所分配到的磁盤(pán)塊中建立兩個(gè)特殊的目錄項(xiàng)“.”和“..”目錄項(xiàng),方法是:首先在用戶(hù)空間中準(zhǔn)備好內(nèi)容,然后以截?cái)鄬?xiě)或者覆蓋寫(xiě)方式調(diào)用do_write()將其寫(xiě)到③中分配到的磁盤(pán)塊中;
⑦ 返回。
6.刪除子目錄函數(shù)rmdir()
(1)對(duì)應(yīng)命令:my_ rmdir
(2)命令調(diào)用格式:my_ rmdir dirname
(1)函數(shù)設(shè)計(jì)格式:void my_rmdir(char *dirname)
(2)功能:在當(dāng)前目錄下刪除名為dirname的子目錄。
(3)輸入:
dirname:欲刪除目錄的目錄名。
(4)輸出:無(wú)。
(5)函數(shù)需完成的工作:
① 調(diào)用do_read()讀入當(dāng)前目錄文件內(nèi)容到內(nèi)存,檢查當(dāng)前目錄下欲刪除目錄文件是否存在,若不存在則返回,并顯示錯(cuò)誤信息;
② 檢查欲刪除目錄文件是否為空(除了“.”和“..”外沒(méi)有其他子目錄和文件),可根據(jù)其目錄項(xiàng)中記錄的文件長(zhǎng)度來(lái)判斷,若不為空則返回,并顯示錯(cuò)誤信息;
③ 檢查該目錄文件是否已經(jīng)打開(kāi),若已打開(kāi)則調(diào)用my_close()關(guān)閉掉;
④ 回收該目錄文件所占據(jù)的磁盤(pán)塊,修改FAT;
⑤ 從當(dāng)前目錄文件中清空該目錄文件的目錄項(xiàng),且free字段置為0:以覆蓋寫(xiě)方式調(diào)用do_write()來(lái)實(shí)現(xiàn);
⑥ 修改當(dāng)前目錄文件的用戶(hù)打開(kāi)表項(xiàng)中的長(zhǎng)度信息,并將表項(xiàng)中的fcbstate置為1;
⑦ 返回。
7.顯示目錄函數(shù)my_ls()
(1)對(duì)應(yīng)命令:my_ls
(2)命令調(diào)用格式:my_ls
(3)函數(shù)設(shè)計(jì)格式:void my_ls(void)
(4)功能:顯示當(dāng)前目錄的內(nèi)容(子目錄和文件信息)。
(5)輸入:無(wú)
(6)輸出:無(wú)
(7)函數(shù)需完成的工作:
① 調(diào)用do_read()讀出當(dāng)前目錄文件內(nèi)容到內(nèi)存;
② 將讀出的目錄文件的信息按照一定的格式顯示到屏幕上;
③ 返回。
8.創(chuàng)建文件函數(shù)my_create()
(1)對(duì)應(yīng)命令:my_create
(2)命令調(diào)用格式:my_create filename
(3)函數(shù)設(shè)計(jì)格式:int my_create (char *filename)
(4)功能:創(chuàng)建名為filename的新文件。
(5)輸入:
filename:新建文件的文件名,可能包含路徑。
(6)輸出:若創(chuàng)建成功,返回該文件的文件描述符(文件打開(kāi)表中的數(shù)組下標(biāo));否則返回-1。
(7)函數(shù)需完成的工作:
① 為新文件分配一個(gè)空閑打開(kāi)文件表項(xiàng),如果沒(méi)有空閑表項(xiàng)則返回-1,并顯示錯(cuò)誤信息;
② 若新文件的父目錄文件還沒(méi)有打開(kāi),則調(diào)用my_open()打開(kāi);若打開(kāi)失敗,則釋放①中為新建文件分配的空閑文件打開(kāi)表項(xiàng),返回-1,并顯示錯(cuò)誤信息;
③ 調(diào)用do_read()讀出該父目錄文件內(nèi)容到內(nèi)存,檢查該目錄下新文件是否重名,若重名則釋放①中分配的打開(kāi)文件表項(xiàng),并調(diào)用my_close()關(guān)閉②中打開(kāi)的目錄文件;然后返回-1,并顯示錯(cuò)誤信息;
④ 檢查FAT是否有空閑的盤(pán)塊,如有則為新文件分配一個(gè)盤(pán)塊,否則釋放①中分配的打開(kāi)文件表項(xiàng),并調(diào)用my_close()關(guān)閉②中打開(kāi)的目錄文件;返回-1,并顯示錯(cuò)誤信息;
⑤ 在父目錄中為新文件尋找一個(gè)空閑的目錄項(xiàng)或?yàn)槠渥芳右粋€(gè)新的目錄項(xiàng);需修改該目錄文件的長(zhǎng)度信息,并將該目錄文件的用戶(hù)打開(kāi)文件表項(xiàng)中的fcbstate置為1;
⑥ 準(zhǔn)備好新文件的FCB的內(nèi)容,文件的屬性為數(shù)據(jù)文件,長(zhǎng)度為0,以覆蓋寫(xiě)方式調(diào)用do_write()將其填寫(xiě)到⑤中分配到的空目錄項(xiàng)中;
⑦ 為新文件填寫(xiě)①中分配到的空閑打開(kāi)文件表項(xiàng),fcbstate字段值為0,讀寫(xiě)指針值為0;
⑧ 調(diào)用my_close()關(guān)閉②中打開(kāi)的父目錄文件;
⑨ 將新文件的打開(kāi)文件表項(xiàng)序號(hào)作為其文件描述符返回。
9.刪除文件函數(shù)my_rm()
(1)對(duì)應(yīng)命令:my_rm
(2)命令調(diào)用格式:my_rm filename
(3)函數(shù)設(shè)計(jì)格式:void my_rm(char *filename)
(4)功能:刪除名為filename的文件。
(5)輸入:
filename:欲刪除文件的文件名,可能還包含路徑。
(6)輸出:無(wú)。
(7)函數(shù)需完成的工作:
① 若欲刪除文件的父目錄文件還沒(méi)有打開(kāi),則調(diào)用my_open()打開(kāi);若打開(kāi)失敗,則返回,并顯示錯(cuò)誤信息;
② 調(diào)用do_read()讀出該父目錄文件內(nèi)容到內(nèi)存,檢查該目錄下欲刪除文件是否存在,若不存在則返回,并顯示錯(cuò)誤信息;
③ 檢查該文件是否已經(jīng)打開(kāi),若已打開(kāi)則關(guān)閉掉;
④ 回收該文件所占據(jù)的磁盤(pán)塊,修改FAT;
⑤ 從文件的父目錄文件中清空該文件的目錄項(xiàng),且free字段置為0:以覆蓋寫(xiě)方式調(diào)用do_write()來(lái)實(shí)現(xiàn);;
⑥ 修改該父目錄文件的用戶(hù)打開(kāi)文件表項(xiàng)中的長(zhǎng)度信息,并將該表項(xiàng)中的fcbstate置為1;
⑦ 返回。
10.打開(kāi)文件函數(shù)my_open()
(1)對(duì)應(yīng)命令:my_open
(2)命令調(diào)用格式:my_open filename
(3)函數(shù)設(shè)計(jì)格式:int my_open(char *filename)
(4)功能:打開(kāi)當(dāng)前目錄下名為filename的文件。
(5)輸入:
filename:欲打開(kāi)文件的文件名
(6)輸出:若打開(kāi)成功,返回該文件的描述符(在用戶(hù)打開(kāi)文件表中表項(xiàng)序號(hào));否則返回-1。
(7)函數(shù)需完成的工作:
① 檢查該文件是否已經(jīng)打開(kāi),若已打開(kāi)則返回-1,并顯示錯(cuò)誤信息;
② 調(diào)用do_read()讀出父目錄文件的內(nèi)容到內(nèi)存,檢查該目錄下欲打開(kāi)文件是否存在,若不存在則返回-1,并顯示錯(cuò)誤信息;
③ 檢查用戶(hù)打開(kāi)文件表中是否有空表項(xiàng),若有則為欲打開(kāi)文件分配一個(gè)空表項(xiàng),若沒(méi)有則返回-1,并顯示錯(cuò)誤信息;
④ 為該文件填寫(xiě)空白用戶(hù)打開(kāi)文件表表項(xiàng)內(nèi)容,讀寫(xiě)指針置為0;
⑤ 將該文件所分配到的空白用戶(hù)打開(kāi)文件表表項(xiàng)序號(hào)(數(shù)組下標(biāo))作為文件描述符fd返回。
11.關(guān)閉文件函數(shù)my_close()
(1)對(duì)應(yīng)命令:my_close
(2)命令調(diào)用格式:my_close fd
(3)函數(shù)設(shè)計(jì)格式:void my_close(int fd)
(4)功能:關(guān)閉前面由my_open()打開(kāi)的文件描述符為fd的文件。
(5)輸入:
fd:文件描述符。
(6)輸出:無(wú)。
(7)函數(shù)需完成的工作:
① 檢查fd的有效性(fd不能超出用戶(hù)打開(kāi)文件表所在數(shù)組的最大下標(biāo)),如果無(wú)效則返回-1;
② 檢查用戶(hù)打開(kāi)文件表表項(xiàng)中的fcbstate字段的值,如果為1則需要將該文件的FCB的內(nèi)容保存到虛擬磁盤(pán)上該文件的目錄項(xiàng)中,方法是:打開(kāi)該文件的父目錄文件,以覆蓋寫(xiě)方式調(diào)用do_write()將欲關(guān)閉文件的FCB寫(xiě)入父目錄文件的相應(yīng)盤(pán)塊中;
③ 回收該文件占據(jù)的用戶(hù)打開(kāi)文件表表項(xiàng)(進(jìn)行清空操作),并將topenfile字段置為0;
④ 返回。
12.寫(xiě)文件函數(shù)my_write()
(1)對(duì)應(yīng)命令:my_write
(2)命令調(diào)用格式:my_write fd
(3)函數(shù)設(shè)計(jì)格式:int my_write(int fd)
(4)功能:將用戶(hù)通過(guò)鍵盤(pán)輸入的內(nèi)容寫(xiě)到fd所指定的文件中。磁盤(pán)文件的讀寫(xiě)操作都必須以完整的數(shù)據(jù)塊為單位進(jìn)行,在寫(xiě)操作時(shí),先將數(shù)據(jù)寫(xiě)在緩沖區(qū)中,緩沖區(qū)的大小與磁盤(pán)塊的大小相同,然后再將緩沖區(qū)中的數(shù)據(jù)一次性寫(xiě)到磁盤(pán)塊中;讀出時(shí)先將一個(gè)磁盤(pán)塊中的內(nèi)容讀到緩沖區(qū)中,然后再傳送到用戶(hù)區(qū)。本實(shí)例為了簡(jiǎn)便起見(jiàn),沒(méi)有設(shè)置緩沖區(qū)管理,只是在讀寫(xiě)文件時(shí)由用戶(hù)使用malloc()申請(qǐng)一塊空間作為緩沖區(qū),讀寫(xiě)操作結(jié)束后使用free()釋放掉。
寫(xiě)操作常有三種方式:截?cái)鄬?xiě)、覆蓋寫(xiě)和追加寫(xiě)。截?cái)鄬?xiě)是放棄原來(lái)文件的內(nèi)容,重新寫(xiě)文件;覆蓋寫(xiě)是修改文件在當(dāng)前讀寫(xiě)指針?biāo)傅奈恢瞄_(kāi)始的部分內(nèi)容;追加寫(xiě)是在原文件的最后添加新的內(nèi)容。在本實(shí)例中,輸入寫(xiě)文件命令后,系統(tǒng)會(huì)出現(xiàn)提示讓用戶(hù)選擇其中的一種寫(xiě)方式,并將隨后鍵盤(pán)輸入的內(nèi)容按照所選的方式寫(xiě)到文件中,鍵盤(pán)輸入內(nèi)容通過(guò)CTR+Z鍵(或其他設(shè)定的鍵)結(jié)束。
(5)輸入:
fd: open()函數(shù)的返回值,文件的描述符;
(6)輸出:實(shí)際寫(xiě)入的字節(jié)數(shù)。
(7)函數(shù)需完成的工作:
① 檢查fd的有效性(fd不能超出用戶(hù)打開(kāi)文件表所在數(shù)組的最大下標(biāo)),如果無(wú)效則返回-1,并顯示出錯(cuò)信息;
② 提示并等待用戶(hù)輸入寫(xiě)方式:(1:截?cái)鄬?xiě);2:覆蓋寫(xiě);3:追加寫(xiě))
③ 如果用戶(hù)要求的寫(xiě)方式是截?cái)鄬?xiě),則釋放文件除第一塊外的其他磁盤(pán)空間內(nèi)容(查找并修改FAT表),將內(nèi)存用戶(hù)打開(kāi)文件表項(xiàng)中文件長(zhǎng)度修改為0,將讀寫(xiě)指針置為0并轉(zhuǎn)④;如果用戶(hù)要求的寫(xiě)方式是追加寫(xiě),則修改文件的當(dāng)前讀寫(xiě)指針位置到文件的末尾,并轉(zhuǎn)④;如果寫(xiě)方式是覆蓋寫(xiě),則直接轉(zhuǎn)④;
④ 提示用戶(hù):整個(gè)輸入內(nèi)容通過(guò)CTR+Z鍵(或其他設(shè)定的鍵)結(jié)束;用戶(hù)可分多次輸入寫(xiě)入內(nèi)容,每次用回車(chē)結(jié)束;
⑤ 等待用戶(hù)從鍵盤(pán)輸入文件內(nèi)容,并將用戶(hù)的本次輸入內(nèi)容保存到一臨時(shí)變量text[]中,要求每次輸入以回車(chē)結(jié)束,全部結(jié)束用CTR+Z鍵(或其他設(shè)定的鍵);
⑥ 調(diào)用do_write()函數(shù)將通過(guò)鍵盤(pán)鍵入的內(nèi)容寫(xiě)到文件中。
⑦ 如果do_write()函數(shù)的返回值為非負(fù)值,則將實(shí)際寫(xiě)入字節(jié)數(shù)增加do_write()函數(shù)返回值,否則顯示出錯(cuò)信息,并轉(zhuǎn)⑨;
⑧ 如果text[]中最后一個(gè)字符不是結(jié)束字符CTR+Z,則轉(zhuǎn)⑦繼續(xù)進(jìn)行寫(xiě)操作;否則轉(zhuǎn)⑨;
⑨ 如果當(dāng)前讀寫(xiě)指針位置大于用戶(hù)打開(kāi)文件表項(xiàng)中的文件長(zhǎng)度,則修改打開(kāi)文件表項(xiàng)中的文件長(zhǎng)度信息,并將fcbstate置1;
⑩ 返回實(shí)際寫(xiě)入的字節(jié)數(shù)。
13.實(shí)際寫(xiě)文件函數(shù)do_write()
(1)對(duì)應(yīng)命令:無(wú)
(2)命令調(diào)用格式:無(wú)
(3)函數(shù)設(shè)計(jì)格式:int my_write(int fd,char *text,int len,char wstyle)
(4)功能:被寫(xiě)文件函數(shù)my_write()調(diào)用,用來(lái)將鍵盤(pán)輸入的內(nèi)容寫(xiě)到相應(yīng)的文件中去。
(5)輸入:
fd: open()函數(shù)的返回值,文件的描述符;
text:指向要寫(xiě)入的內(nèi)容的指針;
len:本次要求寫(xiě)入字節(jié)數(shù)
wstyle:寫(xiě)方式
(6)輸出:實(shí)際寫(xiě)入的字節(jié)數(shù)。
(7)函數(shù)需完成的工作:
① 用malloc()申請(qǐng)1024B的內(nèi)存空間作為讀寫(xiě)磁盤(pán)的緩沖區(qū)buf,申請(qǐng)失敗則返回-1,并顯示出錯(cuò)信息;
② 將讀寫(xiě)指針轉(zhuǎn)化為邏輯塊塊號(hào)和塊內(nèi)偏移off,并利用打開(kāi)文件表表項(xiàng)中的首塊號(hào)及FAT表的相關(guān)內(nèi)容將邏輯塊塊號(hào)轉(zhuǎn)換成對(duì)應(yīng)的磁盤(pán)塊塊號(hào)blkno;如果找不到對(duì)應(yīng)的磁盤(pán)塊,則需要檢索FAT為該邏輯塊分配一新的磁盤(pán)塊,并將對(duì)應(yīng)的磁盤(pán)塊塊號(hào)blkno登記到FAT中,若分配失敗,則返回-1,并顯示出錯(cuò)信息;
③ 如果是覆蓋寫(xiě),或者如果當(dāng)前讀寫(xiě)指針?biāo)鶎?duì)應(yīng)的塊內(nèi)偏移off不等于0,則將塊號(hào)為blkno的虛擬磁盤(pán)塊全部1024B的內(nèi)容讀到緩沖區(qū)buf中;否則便用ASCII碼0清空buf;
④ 將text中未寫(xiě)入的內(nèi)容暫存到緩沖區(qū)buff的第off字節(jié)開(kāi)始的位置,直到緩沖區(qū)滿(mǎn),或者接收到結(jié)束字符CTR+Z為止;將本次寫(xiě)入字節(jié)數(shù)記錄到tmplen中;
⑤ 將buf中1024B的內(nèi)容寫(xiě)入到塊號(hào)為blkno的虛擬磁盤(pán)塊中;
⑥將當(dāng)前讀寫(xiě)指針修改為原來(lái)的值加上tmplen;并將本次實(shí)際寫(xiě)入的字節(jié)數(shù)增加tmplen;
⑦ 如果tmplen小于len,則轉(zhuǎn)②繼續(xù)寫(xiě)入;否則轉(zhuǎn)⑧;
⑧ 返回本次實(shí)際寫(xiě)入的字節(jié)數(shù)。
14.讀文件函數(shù)my_read()
(1)對(duì)應(yīng)命令:my_read
(2)命令調(diào)用格式:my_read fd len
(3)函數(shù)設(shè)計(jì)格式:int myread (int fd, int len)
(4)功能:讀出指定文件中從讀寫(xiě)指針開(kāi)始的長(zhǎng)度為len的內(nèi)容到用戶(hù)空間中。
(5)輸入:
fd: open()函數(shù)的返回值,文件的描述符;
len: 要從文件中讀出的字節(jié)數(shù)。
(6)輸出:實(shí)際讀出的字節(jié)數(shù)。
(7)函數(shù)需完成的工作:
① 定義一個(gè)字符型數(shù)組text[len],用來(lái)接收用戶(hù)從文件中讀出的文件內(nèi)容;
② 檢查fd的有效性(fd不能超出用戶(hù)打開(kāi)文件表所在數(shù)組的最大下標(biāo)),如果無(wú)效則返回-1,并顯示出錯(cuò)信息;
③ 調(diào)用do_read()將指定文件中的len字節(jié)內(nèi)容讀出到text[]中;
④ 如果do_read()的返回值為負(fù),則顯示出錯(cuò)信息;否則將text[]中的內(nèi)容顯示到屏幕上;
⑤ 返回。
15.實(shí)際讀文件函數(shù)do_read()
(1)對(duì)應(yīng)命令:無(wú)
(2)命令調(diào)用格式:無(wú)
(3)函數(shù)設(shè)計(jì)格式:int do_read (int fd, int len,char *text)
(4)功能:被my_read()調(diào)用,讀出指定文件中從讀寫(xiě)指針開(kāi)始的長(zhǎng)度為len的內(nèi)容到用戶(hù)空間的text中。
(5)輸入:
fd: open()函數(shù)的返回值,文件的描述符;
len: 要求從文件中讀出的字節(jié)數(shù)。
text:指向存放讀出數(shù)據(jù)的用戶(hù)區(qū)地址
(6)輸出:實(shí)際讀出的字節(jié)數(shù)。
(7)函數(shù)需完成的工作:
① 使用malloc()申請(qǐng)1024B空間作為緩沖區(qū)buf,申請(qǐng)失敗則返回-1,并顯示出錯(cuò)信息;
② 將讀寫(xiě)指針轉(zhuǎn)化為邏輯塊塊號(hào)及塊內(nèi)偏移量off,利用打開(kāi)文件表表項(xiàng)中的首塊號(hào)查找FAT表,找到該邏輯塊所在的磁盤(pán)塊塊號(hào);將該磁盤(pán)塊塊號(hào)轉(zhuǎn)化為虛擬磁盤(pán)上的內(nèi)存位置;
③ 將該內(nèi)存位置開(kāi)始的1024B(一個(gè)磁盤(pán)塊)內(nèi)容讀入buf中;
④ 比較buf中從偏移量off開(kāi)始的剩余字節(jié)數(shù)是否大于等于應(yīng)讀寫(xiě)的字節(jié)數(shù)len,如果是,則將從off開(kāi)始的buf中的len長(zhǎng)度的內(nèi)容讀入到text[]中;否則,將從off開(kāi)始的buf中的剩余內(nèi)容讀入到text[]中;
⑤ 將讀寫(xiě)指針增加④中已讀字節(jié)數(shù),將應(yīng)讀寫(xiě)的字節(jié)數(shù)len減去④中已讀字節(jié)數(shù),若len大于0,則轉(zhuǎn)②;否則轉(zhuǎn)⑥;
⑥ 使用free()釋放①中申請(qǐng)的buf。
⑦ 返回實(shí)際讀出的字節(jié)數(shù)。
16. 退出文件系統(tǒng)函數(shù)my_exitsys()
(1)對(duì)應(yīng)命令:my_exitsys
(2)命令調(diào)用格式:my_ exitsys
(1)函數(shù)設(shè)計(jì)格式:void my_exitsys()
(2)功能:退出文件系統(tǒng)。
(3)輸入:無(wú)
(4)輸出:無(wú)。
(5)函數(shù)需完成的工作:
① 使用C庫(kù)函數(shù)fopen()打開(kāi)磁盤(pán)上的myfsys文件;
② 將虛擬磁盤(pán)空間中的所有內(nèi)容保存到磁盤(pán)上的myfsys文件中;
③ 使用c語(yǔ)言的庫(kù)函數(shù)fclose()關(guān)閉myfsys文件;
④ 撤銷(xiāo)用戶(hù)打開(kāi)文件表,釋放其內(nèi)存空間
⑤ 釋放虛擬磁盤(pán)空間。
鏈接地址:http://m.hcyjhs8.com/p-6633329.html