操作系統(tǒng)——實驗五

一、實驗簡介

本實驗要求在模擬的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ù)定義:

  1. read_block(int i, char *p);
    該函數(shù)把邏輯塊i的內容讀入到指針p指向的內存位置瓷马,拷貝的字符個數(shù)為存儲塊的長度B。
  2. write block(int i, char *p);
    該函數(shù)把指針p指向的內容寫入邏輯塊i跨晴,拷貝的字符個數(shù)為存儲塊的長度B欧聘。

此外,為了方便測試坟奥,我們還需要實現(xiàn)另外兩個函數(shù):一個用來把數(shù)組ldisk 存儲到文件;另一個用來把文件內容恢復到數(shù)組拇厢。

  1. int backup_disk(FILE *filepath);
    該函數(shù)將內存中現(xiàn)有的ldisk[C][H][B]保存到文件句柄FILE *filepath對應的二進制文件中爱谁。
  2. int restore_disk(FILE *filepath);
    該函數(shù)將從二進制文件句柄FILE *filepath中讀取硬盤數(shù)據(jù),并存儲到內存數(shù)組ldisk[C][H][B]中孝偎。

在IO系統(tǒng)中访敌,我們的文件結構組成為:

  1. iosystem.h用來聲明全局變量與函數(shù)接口。
  2. 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)流程圖

文件系統(tǒng)位于I/O系統(tǒng)之上拥刻。
文件系統(tǒng)的組織結構如下:

  1. filesystem.h用來聲明全局變量與函數(shù)接口。
  2. 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
我們只需要將1001001111111110進行按位與&操作,這樣我們就可以得到正確結果思瘟。

兩個switch-case語句分別對應了修改為01的情況下的位運算類型荸百。

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;
}

文件打開之后才能進行讀寫操作.讀操作需要完成的任務如下:

  1. 計算讀寫指針對應的位置在讀寫緩沖區(qū)中的偏移
  2. 把緩沖區(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)建文件

image.png

image.png

2.刪除文件

image.png

image.png

3.打開文件

已經嵌入到上述展示之中骗露。

4.關閉文件

同上。

5.讀取文件

image.png

image.png

6.寫入文件

image.png

image.png

7.目錄打印

image.png

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;
    
}
image.png

查看目錄血巍,發(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;
    
}
image.png

可以看到萧锉,我們成功把磁盤內容恢復了。

9.位圖打印

int main()
{
    init();
    bitMapOutput();
    create("5555"); 
    bitMapOutput();
}
image.png

image.png

可以看到述寡,位圖如我們預期更改了柿隙。

代碼詳見:https://github.com/Jerlllly/BJTU_operating-system-lesson/tree/master/Lab5

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鲫凶,隨后出現(xiàn)的幾起案子禀崖,更是在濱河造成了極大的恐慌,老刑警劉巖螟炫,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件波附,死亡現(xiàn)場離奇詭異,居然都是意外死亡昼钻,警方通過查閱死者的電腦和手機掸屡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來然评,“玉大人仅财,你說我怎么就攤上這事⊥胩剩” “怎么了盏求?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亿眠。 經常有香客問我碎罚,道長,這世上最難降的妖魔是什么缕探? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任魂莫,我火速辦了婚禮还蹲,結果婚禮上爹耗,老公的妹妹穿的比我還像新娘。我一直安慰自己谜喊,他們只是感情好潭兽,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斗遏,像睡著了一般山卦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诵次,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天账蓉,我揣著相機與錄音枚碗,去河邊找鬼。 笑死铸本,一個胖子當著我的面吹牛肮雨,可吹牛的內容都是我干的。 我是一名探鬼主播箱玷,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怨规,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锡足?” 一聲冷哼從身側響起波丰,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舶得,沒想到半個月后掰烟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡沐批,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年媚赖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珠插。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡惧磺,死狀恐怖,靈堂內的尸體忽然破棺而出捻撑,到底是詐尸還是另有隱情磨隘,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布顾患,位于F島的核電站番捂,受9級特大地震影響,放射性物質發(fā)生泄漏江解。R本人自食惡果不足惜设预,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望犁河。 院中可真熱鬧鳖枕,春花似錦、人聲如沸桨螺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灭翔。三九已至魏烫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哄褒。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工稀蟋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呐赡。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓糊治,卻偏偏與公主長得像,于是被迫代替她去往敵國和親罚舱。 傳聞我的和親對象是個殘疾皇子井辜,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容

  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應的列上鍵入重復值時,會觸發(fā)此異常管闷。 O...
    我想起個好名字閱讀 5,317評論 0 9
  • 一粥脚、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,746評論 0 10
  • 21.1文件系統(tǒng)的概念 21.1.1文件系統(tǒng)和文件 ■文件系統(tǒng)是操作系統(tǒng)中管理持久性數(shù)據(jù)的子系統(tǒng),提供數(shù)據(jù)存儲和訪...
    龜龜51閱讀 725評論 0 4
  • Linux系統(tǒng)一般有4個主要部分:內核包个、shell刷允、文件系統(tǒng)和應用程序。 內核碧囊、shell和文件系統(tǒng)一起形成了基本...
    請愛護小動物閱讀 2,570評論 0 22
  • Linux系統(tǒng)一般有4個主要部分: 內核树灶、shell、文件系統(tǒng)和應用程序糯而。內核天通、shell和文件系統(tǒng)一起形成了基本...
    偷風箏的人_閱讀 3,255評論 1 17