一、實驗簡介
本實驗要求在模擬的I/O系統(tǒng)之上開發(fā)一個簡單的文件系統(tǒng)断箫。用戶通過create, open, read等命令與文件系統(tǒng)交互。文件系統(tǒng)把磁盤視為順序編號的邏輯塊序列秋冰,邏輯塊的編號為0至L ? 1仲义。I/O系統(tǒng)利用內存中的數(shù)組模擬磁盤。
二剑勾、I/O系統(tǒng)
實際物理磁盤的結構是多維的:有柱面埃撵、磁頭、扇區(qū)等概念虽另。I/O系統(tǒng)的任務是隱藏磁盤的結構細節(jié)暂刘,把磁盤以邏輯塊的面目呈現(xiàn)給文件系統(tǒng)。邏輯塊順序編號捂刺,編號取值范圍為0至L?1谣拣,其中L表示磁盤的存儲塊總數(shù)募寨。實驗中,我們可以利用數(shù)組ldisk[C][H][B]
構建磁盤模型森缠,其中CHB 分別表示柱面號拔鹰,磁頭號和扇區(qū)號。每個扇區(qū)大小為512字節(jié)贵涵。I/O系統(tǒng)從文件系統(tǒng)接收命令列肢,根據(jù)命令指定的邏輯塊號把磁盤塊的內容讀入命令指定的內存區(qū)域,或者把命令指定的內存區(qū)域內容寫入磁盤塊宾茂。文件系統(tǒng)和I/O系統(tǒng)之間的接口由如下兩個函數(shù)定義:
-
read_block(int i, char *p);
該函數(shù)把邏輯塊i的內容讀入到指針p指向的內存位置瓷马,拷貝的字符個數(shù)為存儲塊的長度B。 -
write block(int i, char *p);
該函數(shù)把指針p指向的內容寫入邏輯塊i跨晴,拷貝的字符個數(shù)為存儲塊的長度B欧聘。
此外,為了方便測試坟奥,我們還需要實現(xiàn)另外兩個函數(shù):一個用來把數(shù)組ldisk 存儲到文件;另一個用來把文件內容恢復到數(shù)組拇厢。
-
int backup_disk(FILE *filepath);
該函數(shù)將內存中現(xiàn)有的ldisk[C][H][B]
保存到文件句柄FILE *filepath
對應的二進制文件中爱谁。 -
int restore_disk(FILE *filepath);
該函數(shù)將從二進制文件句柄FILE *filepath
中讀取硬盤數(shù)據(jù),并存儲到內存數(shù)組ldisk[C][H][B]
中孝偎。
在IO系統(tǒng)中访敌,我們的文件結構組成為:
-
iosystem.h
用來聲明全局變量與函數(shù)接口。 -
iosystem.c
用來定義函數(shù)與實現(xiàn)變量衣盾。
在iosystem.h
中:
#define C 80
#define H 2
#define B 18
定義了我們物理硬盤的柱面號寺旺,磁頭號和扇區(qū)號的最大值。
unsigned char *ldisk[C][H][B];
int init_ldisk();
int read_block(int i,unsigned char *p);
int write_block(int i,unsigned char *p);
int backup_disk(FILE *filepath);
int restore_disk(FILE *filepath);
聲明了我們IO系統(tǒng)對外的接口與物理硬盤ldisk的數(shù)組結構。
unsigned char *ldisk[C][H][B]
是一個unsigned char
類型的指針數(shù)組。
在iosystem.c
中巷蚪,我們查看相關函數(shù)的實現(xiàn):
int init_ldisk()
{
for(int i=0;i<C;i++)
{
for(int j=0;j<H;j++)
{
for(int k=0;k<B;k++)
{
ldisk[i][j][k]=(unsigned char *)malloc(sizeof(unsigned char)*512);
}
}
}
printf("IO INFO,logic disk init successfuly.\n");
return 0;
}
這是初始化物理硬盤的函數(shù)军俊,通過一個三重循環(huán)來對指針數(shù)組申請內存空間,根據(jù)題意秤掌,每個扇區(qū)我們申請了512B的大小。
int read_block(int i,unsigned char *p)
{
if (i >= C*H*B)
{
printf("IO ERROR,index out of range!\n");
return -1;
}
int CylinderIndex=i/(H*B);
int SectorIndex=i%B+1;
int HeadsIndex=(i/18)%2;
memcpy(p,ldisk[CylinderIndex][HeadsIndex][SectorIndex-1],512);
printf("IO INFO,read logic index is %d,physic index is %d,%d,%d,the content is %s.\n",i,CylinderIndex,HeadsIndex,SectorIndex,ldisk[CylinderIndex][HeadsIndex][SectorIndex-1]);
return 0;
}
這是讀取邏輯塊的函數(shù),其參數(shù)int i,unsigned char *p
分別為需要讀取的邏輯塊號與返回結果的指針走搁。在函數(shù)體中,我們通過模運算與取整運算將邏輯塊號轉化為物理三維塊號迈窟,并使用memcpy()
函數(shù)將對應內存空間的數(shù)據(jù)拷貝給返回指針p私植。
int write_block(int i,unsigned char *p)
{
if (i >= C*H*B)
{
printf("IO ERROR,index out of range!\n");
return -1;
}
int CylinderIndex=i/(H*B);
int SectorIndex=i%B+1;
int HeadsIndex=(i/18)%2;
memcpy(ldisk[CylinderIndex][HeadsIndex][SectorIndex-1],p,512);
printf("IO INFO,write logic index is %d,physic index is %d,%d,%d,the content is %s.\n",i,CylinderIndex,HeadsIndex,SectorIndex,p);
return 0;
}
這是寫入邏輯塊的函數(shù),其參數(shù)int i,unsigned char *p
分別為需要寫入的邏輯塊號與輸入數(shù)據(jù)的指針车酣。在函數(shù)體中曲稼,我們通過模運算與取整運算將邏輯塊號轉化為物理三維塊號索绪,并使用memcpy()
函數(shù)將對應指針的數(shù)據(jù)拷貝給對應內存空間的指針。
int backup_disk(FILE *filepath)
{
if(filepath==NULL)
{
printf("IO ERROR,filepath open fail");
return -1;
}
for(int i=0;i<C;i++)
{
for(int j=0;j<H;j++)
{
for(int k=0;k<B;k++)
{
fwrite(ldisk[i][j][k],sizeof(unsigned char),512,filepath);
}
}
}
fclose(filepath);
printf("IO INFO,backup successfuly.\n");
return 0;
}
根據(jù)實驗要求躯肌,我設計了備份函數(shù)者春,可以將虛擬在內存中的物理硬盤數(shù)據(jù)空間保存為文件,文件的儲存方式為二進制儲存清女,這樣方便我們在恢復的時候直接讀取钱烟。
int restore_disk(FILE *filepath)
{
if(filepath==NULL)
{
printf("IO ERROR,filepath open fail");
return -1;
}
for(int i=0;i<C;i++)
{
for(int j=0;j<H;j++)
{
for(int k=0;k<B;k++)
{
fread(ldisk[i][j][k],sizeof(unsigned char),512,filepath);
}
}
}
fclose(filepath);
printf("IO INFO,restore backup successfuly.\n");
return 0;
}
根據(jù)實驗要求,我設計了恢復備份函數(shù)嫡丙,可以讀取硬盤中的二進制文件拴袭,并將其恢復到我們虛擬的內存硬盤空間之中。
三曙博、文件系統(tǒng)
文件系統(tǒng)位于I/O系統(tǒng)之上拥刻。
文件系統(tǒng)的組織結構如下:
-
filesystem.h
用來聲明全局變量與函數(shù)接口。 -
filesystem.c
用來定義函數(shù)與實現(xiàn)變量父泳。
typedef struct
{
int fileSize;
int blockList[3];
}fileDescriptorItem;
我們定義了名為fileDescriptorItem
的文件描述符結構體類型般哼,其中fileSize
為文件大小,blockList[3]
為這個文件所分配的邏輯塊號惠窄,最多每個文件可分配3塊蒸眠。
typedef struct
{
unsigned char fileName[28];
int fileDescriptorIndex;
}dictionaryItem;
我們定義了名為dictionaryItem
的目錄結構體類型,其中fileName
為文件名稱杆融,fileDescriptorIndex
為這個文件所分配的文件描述符的序號楞卡,最多每個文件名最長為28字節(jié)。
fileDescriptorItem *fileDescriptor[7];
unsigned char *bitMap;
dictionaryItem *dictionary;
在這里脾歇,我們定義了三個指針蒋腮,分別為文件描述符指針數(shù)組、位圖指針藕各、目錄指針池摧,其中文件描述符指針數(shù)組大小為7。
int init()
{
printf("\nFILE INFO,file system will init.\n");
init_ldisk();
bitMap=(unsigned char*)calloc(512,sizeof(unsigned char));
for(int i=0;i<512;i++)
{bitMap[i]=0;}
bitMap[0]=0xff;
write_block(0,bitMap);
for(int i=0;i<7;i++)
{
fileDescriptor[i]=(fileDescriptorItem*)calloc(sizeof(unsigned char)*512/sizeof(fileDescriptorItem),sizeof(fileDescriptorItem));
write_block(i+1,(unsigned char*)fileDescriptor[i]);
}
printf("FILE INFO,file system init finished.\n");
return 0;
}
在這個函數(shù)中激况,我們對位圖险绘、文件描述符進行了初始化,對指針分配了內存空間誉碴,并將所有更改寫入到硬盤之中宦棺。
int bitMapUpdate(int flag,int index)
{
printf("\nFILE INFO,bitmap is updating.\n");
read_block(0,bitMap);
int temp=index%8;
if(flag==1){
switch(temp)
{
case 0:bitMap[index/8]=bitMap[index/8]|0x80;break;
case 1:bitMap[index/8]=bitMap[index/8]|0x40;break;
case 2:bitMap[index/8]=bitMap[index/8]|0x20;break;
case 3:bitMap[index/8]=bitMap[index/8]|0x10;break;
case 4:bitMap[index/8]=bitMap[index/8]|0x08;break;
case 5:bitMap[index/8]=bitMap[index/8]|0x04;break;
case 6:bitMap[index/8]=bitMap[index/8]|0x02;break;
case 7:bitMap[index/8]=bitMap[index/8]|0x01;break;
}}
else if(flag==0)
{
switch(temp)
{
case 0:bitMap[index/8]=bitMap[index/8]&0x7f;break;
case 1:bitMap[index/8]=bitMap[index/8]&0xbf;break;
case 2:bitMap[index/8]=bitMap[index/8]&0xdf;break;
case 3:bitMap[index/8]=bitMap[index/8]&0xef;break;
case 4:bitMap[index/8]=bitMap[index/8]&0xf7;break;
case 5:bitMap[index/8]=bitMap[index/8]&0xfb;break;
case 6:bitMap[index/8]=bitMap[index/8]&0xfd;break;
case 7:bitMap[index/8]=bitMap[index/8]&0xfe;break;
}
}
write_block(0,bitMap);
printf("FILE INFO,bitmap updated.\n");
}
這個函數(shù)是對位圖進行更新操作的函數(shù),參數(shù)int flag,int index
分別是指將位圖修改為0 or 1 與修改的位圖序號黔帕。在函數(shù)體中代咸,我們先讀取了硬盤中對應塊號的位圖,另外成黄,由于C語言中沒有對二進制的直接修改操作呐芥,所以在這里我們使用位運算來代替逻杖,比如我們舉例如下:
位圖中一個字節(jié)
10010011
現(xiàn)在我們希望將其最后一位1修改為0
我們只需要將10010011
與11111110
進行按位與&
操作,這樣我們就可以得到正確結果思瘟。
兩個switch-case
語句分別對應了修改為0
或1
的情況下的位運算類型荸百。
int findFreeBitMap()
{
printf("\nFILE INFO,is finding free bitmap.\n");
read_block(0,bitMap);
for(int i=0;i<512;i++)
{
printf("%d",bitMap[i]);
if(bitMap[i]!=0xff)
{
for(int j=0;j<8;j++)
{
int a=bitMap[i];
if(a==0)
{
printf("\nFILE INFO,found free bitmap:%d.\n",i*8+j);
return i*8+j;
}
}
}
}
printf("\nFILE ERROR,can't find free bitmap.\n");
return -1;
}
這個函數(shù)用來尋找位圖中空閑的下一位,如果尋找成功返回序號滨攻,尋找失敗返回-1够话。
int bitMapOutput()
{
printf("\nFILE INFO,bitmap output:\n");
for(int i=0;i<512;i++)
{
if(bitMap[i]==0)
printf("00000000");
else
{
for(int j=7;j>=0;j--)
{
int a=bitMap[i];
printf("%d",(a>>j)&0x01);
}
}
if((i+1)%16==0 && i!=0)
printf("\n");
}
printf("\nFILE INFO,bitmap output finished.\n");
}
這個函數(shù)可以將位圖按照一定格式打印出來,在這里值得注意的是我們使用位運算來實現(xiàn)讀取每一位光绕。先右移女嘲,再與00000001
進行&
操作,這樣便得到了每一位诞帐。
int fileDescriptorInsert(int fileSize,int blockList[3])
{
printf("\nFILE INFO,file descriptor is inserting.\n");
for(int i=0;i<7;i++)
{
read_block(i+1,(unsigned char*)fileDescriptor[i]);
}
for(int i=0;i<7;i++)
{
for(int j=0;j<sizeof(unsigned char)*512/sizeof(fileDescriptorItem);j++)
{
if (fileDescriptor[i][j].fileSize==0 && fileDescriptor[i][j].blockList[0]==0 && fileDescriptor[i][j].blockList[1]==0 && fileDescriptor[i][j].blockList[2]==0)
{
fileDescriptor[i][j].fileSize=fileSize;
fileDescriptor[i][j].blockList[0]= blockList[0];
fileDescriptor[i][j].blockList[1]= blockList[1];
fileDescriptor[i][j].blockList[2]= blockList[2];
for(int l=0;l<7;l++)
{
write_block(l+1,(unsigned char*)fileDescriptor[l]);
}
printf("FILE INFO,file descriptor inserted.\n");
return i*sizeof(unsigned char)*512/sizeof(fileDescriptorItem)+j;
}
}
}
printf("FILE ERROR,can't insertfile descriptor.\n");
return -1;
}
這個函數(shù)的功能是插入文件描述符欣尼。首先讀取文件描述符所對應的邏輯塊到內存中,之后尋找空的文件描述符位置停蕉,然后進行相應的修改操作愕鼓,最后將所有修改寫入物理硬盤中。
int fileDescriptorUpdate(int index,int fileSize,int blockList[3])
{
printf("\nFILE INFO,file descriptor is updating.\n");
for(int i=0;i<7;i++)
{
read_block(i+1,(unsigned char*)fileDescriptor[i]);
}
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].fileSize=fileSize;
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[0]= blockList[0];
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[1]= blockList[1];
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[2]= blockList[2];
for(int l=0;l<7;l++)
{
write_block(l+1,(unsigned char*)fileDescriptor[l]);
}
printf("FILE INFO,file descriptor updated.\n");
return 0;
}
這個函數(shù)是用來更新文件描述符慧起,首先讀取文件描述符所對應的邏輯塊到內存中菇晃,然后進行相應的修改操作,最后將所有修改寫入物理硬盤中完慧。
int fileDescriptorDelete(int index)
{
printf("\nFILE INFO,file descriptor is deleting.\n");
for(int i=0;i<7;i++)
{
read_block(i+1,(unsigned char*)fileDescriptor[i]);
}
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].fileSize=0;
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[0]= 0;
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[1]= 0;
fileDescriptor[index/(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))][index%(sizeof(unsigned char)*512/sizeof(fileDescriptorItem))].blockList[2]= 0;
for(int l=0;l<7;l++)
{
write_block(l+1,(unsigned char*)fileDescriptor[l]);
}
printf("FILE INFO,file descriptor deleted.\n");
return 0;
}
這個函數(shù)的功能是用來刪除文件描述符谋旦,參數(shù)為刪除文件描述符的序號剩失,進入函數(shù)體之后先從硬盤對應邏輯塊讀取文件描述符屈尼,之后進行對應修改,最后將所有內存中的文件描述符寫會到硬盤中拴孤。
int initDic()
{
printf("FILE INFO,is initing dic.\n");
dictionary=(dictionaryItem*)calloc(sizeof(unsigned char)*512/sizeof(dictionaryItem),sizeof(dictionaryItem)) ;
int index=findFreeBitMap();
write_block(index,(unsigned char*)dictionary);
bitMapUpdate(1,index);
int blockList[3]={index};
int descriptorIndex=fileDescriptorInsert(1,blockList);
strncpy(dictionary[0].fileName,"Dictionary",strlen("Dictionary"));
dictionary[0].fileDescriptorIndex=descriptorIndex;
write_block(index,(unsigned char*)dictionary);
printf("FILE INFO,inited dic.\n");
return 0;
}
這個是用來初始化目錄的函數(shù)脾歧,我們給目錄指針分配了內存空間,并將其寫入到硬盤之中演熟,需要注意的是里面對于位圖的分配與文件描述符的建立鞭执。
int readDic()
{
for(int i=0;i<7;i++)
{
read_block(i+1,(unsigned char*)fileDescriptor[i]);
}
int i0=fileDescriptor[0][0].blockList[0];
int i1=fileDescriptor[0][0].blockList[1];
int i2=fileDescriptor[0][0].blockList[2];
if(i0!=0)
{
read_block(i0,(unsigned char*)dictionary);
}
if(i1!=0)
{
read_block(i0,(unsigned char*)dictionary+512);
}
if(i2!=0)
{
read_block(i0,(unsigned char*)dictionary+512);
}
return 0;
}
這個是用來將目錄從邏輯塊中讀取到內存中,由于目錄最多可能有三塊芒粹,所以我們需要先找到目錄的文件描述符兄纺,然后根據(jù)blockList
里面的參數(shù)情況來分別讀取。
int create(unsigned char *filename)
{
printf("\nFILE INFO,is creating file,filename is %s\n",filename);
int flag=0;
read_block(0,bitMap);
for(int i=1;i<512;i++)
{
if(bitMap[i]!=0)
{
flag=1;
break;
}
}
if(flag==0)
{
initDic();
}
/*Check dic is full or not*/
readDic();
CheckDic();
int FileDescriptorNum,MenuItemNum,DiskNum;
MenuItemNum = SearchMenuItem();
strcpy(menuitem[MenuItemNum].FileName,filename);
FileDescriptorNum = SearchFileDescriptor();
menuitem[MenuItemNum].FileDescriptorNum = FileDescriptorNum;
DiskNum = SearchBitMap();
filedescriptor[FileDescriptorNum].DiskNum[0] = DiskNum;
filedescriptor[FileDescriptorNum].IsFree = 'N';
return 0;
}
這個是建立文件函數(shù)化漆,參數(shù)為所建立的文件名稱估脆,首先讀取位圖,并查找空閑的位座云,之后查看目錄書否建立疙赠,如果沒有建立執(zhí)行相關操作付材,讀取目錄與文件描述符,并尋找空的目錄項與文件描述符項圃阳,寫入修改厌衔,最后寫入到硬盤上。
int destroy(char* filename)
{
int temp = 1;
int pos = 0;
for (int i = 0; i < B_MAX; i++)
{
if (ldisk[0][0][i].flag == '1')
{
if (strcmp(ldisk[0][0][i].data, filename)== 0)
{
pos = i;
break;
}
}
}
if (pos == 0)
{
cout << "FILE ERROR,can't delete.\n" << endl;
}
else {
ldisk[0][0][pos].flag = '0';
ldisk[0][0][pos].data[0] = '\0';
ldisk[0][0][pos].next = NULL;
cout << "FILE INFO,deleted." << endl;
}
return 0;
}
這個函數(shù)用來根據(jù)文件名刪除對應文件捍岳,需要注意的是刪除時對文件描述符富寿、邏輯塊、目錄項祟同、位圖等的具體操作作喘,并寫入更改到硬盤之中。
int open(char* filename)
{
int pos = 0;
for (int i = 0; i < B_MAX; i++)
{
if (ldisk[0][0][i].flag == '1')
{
if (strcmp(ldisk[0][0][i].data, filename)==0)
{
pos = i;
break;
}
}
}
if (pos == 0)
{
cout << "FILE ERROR,can't open.\n" << endl;
}
else {
cout << "FILE INFO,opened." << endl;
for (int j = 0; j < C_MAX; j++)
{
if (item[j].index == 0)
{
item[j].index = 19706500 + j;
item[j].pos = 0;
item[j].data = ldisk[0][0][pos].next;
cout << "index: " << item[j].index << endl;
return item[j].index;
}
}
}
return 0;
}
文件系統(tǒng)維護一張打開文件表.打開文件表的長度固定晕城,其表目包含如下信息:
?讀寫緩沖區(qū)
? 讀寫指針
? 文件描述符號
文件被打開時泞坦,便在打開文件表中為其分配一個表目;文件被關閉時砖顷,其對應的表目被釋放贰锁。讀寫緩沖區(qū)的大小等于一個磁盤存儲塊。打開文件時需要進行的操作如下:
? 搜索目錄找到文件對應的描述符編號
? 在打開文件表中分配一個表目
? 在分配到的表目中把讀寫指針置為0滤蝠,并記錄描述符編號
? 讀入文件的第一塊到讀寫緩沖區(qū)中
? 返回分配到的表目在打開文件表中的索引號
int close(int index)
{
for (int j = 0; j < C_MAX; j++)
{
if (item[j].index == index)
{
item[j].index == 0;
item[j].pos = 0;
item[j].data = NULL;
}
}
cout << "FILE INFO,closed." << endl;
return 0;
}
關閉文件時需要進行的操作如下:
? 把緩沖區(qū)的內容寫入磁盤
? 釋放該文件在打開文件表中對應的表目
? 返回狀態(tài)信息
int read(int index, string mem_area, int count)
{
for (int j = 0; j < C_MAX; j++)
{
if (item[j].index == index)
{
for (int i = 0; i < count; i++)
{
mem_area[i] = item[j].data->data[i + item[j].pos];
cout << mem_area[i];
}
cout << "FILE INFO,read." << endl;
return 0;
}
}
cout << "FILE ERROR,can't read.'" << endl;
return 0;
}
文件打開之后才能進行讀寫操作.讀操作需要完成的任務如下:
- 計算讀寫指針對應的位置在讀寫緩沖區(qū)中的偏移
- 把緩沖區(qū)中的內容拷貝到指定的內存位置豌熄,直到發(fā)生下列事件之一:
? 到達文件尾或者已經拷貝了指定的字節(jié)數(shù)。這時物咳,更新讀寫指針并返回相應信息
? 到達緩沖區(qū)末尾锣险。這時,把緩沖區(qū)內容寫入磁盤览闰,然后把文件下一塊的內容讀入磁盤芯肤。最后返回第2步。
int write(int index, string mem_area, int count)
{
for (int j = 0; j < C_MAX; j++)
{
if (item[j].index == index)
{
myblock* p = item[j].data;
for (int i = 0; i < count; i++)
{
if (i+1 % 512 == 0)
{
p->next = NULL;
p = p->next;
}
p->data[item[j].pos] = mem_area[i];
item[j].pos++;
}
cout << "FILE INFO,wirtten." << endl;
return 0;
}
}
cout << "FILE ERROR,can't write." << endl;
return 0;
}
寫文件時压鉴,須在相應系統(tǒng)調用中給出文件名和其在內存源地址崖咨。此時,系統(tǒng)要查找目錄油吭,找到指定目錄項击蹲,從再利用目錄中的寫指針進行寫操作。設置文件讀/寫指針的位置婉宰,以便每次讀/寫文件時歌豺,不需要從始端開始而是從所設置的位置開始操作⌒陌可以改順序存取為隨機存取类咧。
四、測試
在這部分,我們將利用命令行測試上述編寫的文件系統(tǒng)轮听。
1.創(chuàng)建文件
2.刪除文件
3.打開文件
已經嵌入到上述展示之中骗露。
4.關閉文件
同上。
5.讀取文件
6.寫入文件
7.目錄打印
8.備份與恢復
進入程序的開發(fā)者模式進行以下操作:
我們先進行備份測試:
int main()
{
init_ldisk();
write_block(2581,"55555555555555555");
FILE *fp=fopen("backupFile.bin","wb");
backup_disk(fp);
// init_ldisk();
// FILE *fp=fopen("backupFile.bin","rb");
// restore_disk(fp);
// char *p=(char*)malloc(sizeof(unsigned char)*512);
// read_block(2581,p);
// printf("%s\n",p);
// printf("\n");
system("pause");
return 0;
}
查看目錄血巍,發(fā)現(xiàn)備份文件:
下面我們進行恢復的測試:
int main()
{
// init_ldisk();
// write_block(2581,"55555555555555555");
// FILE *fp=fopen("backupFile.bin","wb");
// backup_disk(fp);
init_ldisk();
FILE *fp=fopen("backupFile.bin","rb");
restore_disk(fp);
char *p=(char*)malloc(sizeof(unsigned char)*512);
read_block(2581,p);
printf("%s\n",p);
printf("\n");
system("pause");
return 0;
}
可以看到萧锉,我們成功把磁盤內容恢復了。
9.位圖打印
int main()
{
init();
bitMapOutput();
create("5555");
bitMapOutput();
}
可以看到述寡,位圖如我們預期更改了柿隙。
代碼詳見:https://github.com/Jerlllly/BJTU_operating-system-lesson/tree/master/Lab5