天天看點

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

目錄

1 實驗簡介

2 I/O系統

相關參數與資料結構

3 檔案系統

3.1 使用者與檔案系統之間的接口

3.2 檔案系統的組織

初始化

3.3 目錄

顯示目錄

3.4 檔案的建立與删除

建立

删除

3.5 檔案的打開與關閉

打開

關閉

3.6 讀寫

3.7 檔案清單

3.8磁盤資訊顯示

3.9檔案詳細資訊檢視

3.10位圖資訊

3.11檔案移動

4 測試

4.1 菜單

4.2 建立檔案

4.3 檢視檔案清單

4.4 檢視位圖資訊

4.5 打開/關閉檔案

4.6 删除檔案

4.7 移動檔案

4.8 檢視/修改檔案内容

4.9 檢視檔案詳情

4.10 檢視磁盤存儲情況(512*64)

5 總結 

1 實驗簡介

本實驗要求在模拟的I/O系統之上開發一個簡單的檔案系統。使用者通過create, open, read等指令與檔案系統互動。檔案系統把磁盤視為順序編号的邏輯塊序列,邏輯塊的編号為0至L −1。I/O系統利用記憶體中的數組模拟磁盤。

2 I/O系統

實際實體磁盤的結構是多元的:有柱面、磁頭、扇區等概念。I/O系統的任務是隐藏磁盤的結構細節,把磁盤以邏輯塊的面目呈現給檔案系統。邏輯塊順序編号,編号取值範圍為0至L−1,其中L表示磁盤的存儲塊總數。實驗中,我們可以利用數組ldisk[C][H][B]建構磁盤模型,其中CHB分别表示柱面号,磁頭号和扇區号。每個扇區大小為512位元組。I/O系統從檔案系統接收指令,根據指令指定的邏輯塊号把磁盤塊的内容讀入指令指定的記憶體區域,或者把指令指定的記憶體區域内容寫入磁盤塊。檔案系統和I/O系統之間的接口由如下兩個函數定義:

• read_block(int i, char *p);

該函數把邏輯塊i的内容讀入到指針p指向的記憶體位置,拷貝的字元個數為存儲塊的長度B。

• write block(int i, char *p);

該函數把指針p指向的内容寫入邏輯塊i,拷貝的字元個數為存儲塊的長度B。此外,為了友善測試,我們還需要實作另外兩個函數:一個用來把數組ldisk 存儲到檔案;另一個用來把檔案内容恢複到數組。

相關參數與資料結構

//磁盤總大小為512*64
#define B        512       			//定義存儲塊的長度B位元組
#define L        64        			//定義磁盤的存儲塊總數L,邏輯号0-(L-1)
#define K        3      			//磁盤的前k 個塊是保留區

#define OK       1     				//操作成功
#define ERROR    0    				//操作錯誤

#define File_Block_Length    (B-3)  //定義檔案磁盤塊号數組長度
#define File_Name_Length     (B-1)  //定義檔案名的長度

//8*8共表示64個邏輯塊,即磁盤的總塊數:L
#define map_row_num     8           //位圖的行數
#define map_cow_num     8           //位圖的列數

#define maxDirectoryNumber  49      //定義目錄中目錄項(檔案數量)的最大值

#define Buffer_Length 64            //定義讀寫緩沖區的大小,用于打開檔案表項

typedef struct FileDescriptor{//檔案描述符
	int fileLength;                                        //檔案長度。機關:位元組
	int file_allocation_blocknumber[File_Block_Length];    //檔案配置設定到的磁盤塊号數組
	int file_block_length;                                 //檔案配置設定到的磁盤塊号數組實際長度
	int beginpos;                                          //檔案的起始坐标位置beginpos=map_cow_num*row + cow
	int rwpointer;                                         //讀寫指針:初始化為0,随着RWBuffer變化
	char RWBuffer[Buffer_Length];                          //讀寫緩沖區,存檔案的内容
}FileDescriptor;

typedef struct Directory{//目錄項,此處僅代表檔案

	int  index;                     						//檔案描述符序号
	int  count;                     						//用于目錄中記錄檔案的數量
	char fileName[File_Name_Length];						//檔案名
	int  isFileFlag;                						//判斷是檔案和是目錄,1為檔案,0為目錄
	int  isOpenFlag;                						//判斷檔案是否打開,1為打開,0為關閉
	FileDescriptor fileDescriptor;  						//檔案描述符資訊,與index 對應
}Directory;


char ldisk[L][B];											//建構磁盤模型

char memory_area[L*(B - K)];								//定義一個足夠長的字元數組
char mem_area[L*(B - K)] = { '\0' };
Directory Directorys[maxDirectoryNumber + 1];				//包括目錄在内,共有目錄項maxDirectoryNumber+1,Directorys[0]儲存目錄
int bitMap[map_row_num][map_cow_num];						// 0:磁盤塊空閑;1:磁盤塊使用
           

3 檔案系統

檔案系統位于I/O系統之上。

3.1 使用者與檔案系統之間的接口

檔案系統需提供如下函數;create, destroy, open, read, write。

• create(filename): 根據指定的檔案名建立新檔案。

• destroy(filename): 删除指定檔案。

• open(filename): 打開檔案。該函數傳回的索引号可用于後續的read, write, lseek,或close操作。

• close(index): 關閉制定檔案。

• read(index, mem_area, count): 從指定檔案順序讀入count個位元組memarea指定的記憶體位置。讀操作從檔案的讀寫指針訓示的位置開始。

• write(index, mem_area, count): 把memarea指定的記憶體位置開始的count個位元組順序寫入指定檔案。寫操作從檔案的讀寫指針訓示的位置開始。

• lseek(index, pos): 把檔案的讀寫指針移動到pos指定的位置。pos是一個整數,表示從檔案開始位置的偏移量。檔案打開時,讀寫指針自動設定為0。每次讀寫操作之後,它指向最後被通路的位元組的下一個位置。lseek能夠在不進行讀寫操作的情況下改變讀寫指針能位置。

• directory: 清單顯示所有檔案及其長度。

3.2 檔案系統的組織

磁盤的前k個塊是保留區,其中包含如下資訊:位圖和檔案描述符。位圖用來描述磁盤塊的配置設定情況。位圖中的每一位對應一個邏輯塊。建立或者删除檔案,以及檔案的長度發生變化時,檔案系統都需要進行位圖操作。前k個塊的剩餘部分包含一組檔案描述符。每個檔案描述符包含如下資訊:

• 檔案長度,機關位元組

• 檔案配置設定到的磁盤塊号數組。該數組的長度是一個系統參數。在實驗中我們可以把它設定為一個比較小的數,例如3。

初始化

/**
 * 函數名:Init
 * 函數功能:初始化檔案系統:初始化位圖(0表示空閑,1表示被占用);初始化0号檔案描述符;
 */
void Init(){
    int i, j;//兩個計數量
    /*初始化磁盤*/
    for (i = 0; i<L; i++){
        for (j = 0; j<B; j++){
            ldisk[i][j] = '\0';//初始化為空
        }
    }
    /*初始化目錄項*/
    for (i = 0; i <= maxDirectoryNumber; i++){
        for (j = 0; j<File_Name_Length; j++){
            Directorys[i].fileName[j] = '\0';    //初始化名字為'\0'
        }
        
        if (i == 0){//第一個為目錄
            Directorys[i].index = 0;                //目錄檔案描述符序号為0
            Directorys[i].isFileFlag = 0;
            Directorys[i].count = 0;
        }
        else{//其他均表示檔案
            Directorys[i].index = -1;          //初始化檔案描述符序号為-1
            Directorys[i].count = -1;           //其他檔案項不記錄count值
            Directorys[i].isFileFlag = 1;       //初始化其他目錄項均為檔案
            Directorys[i].isOpenFlag = 0;       //檔案均關閉
            /*配置檔案描述符的相關項*/
            
            memset(Directorys[i].fileDescriptor.file_allocation_blocknumber, -1, File_Block_Length);
            //初始化磁盤号數組為-1
            Directorys[i].fileDescriptor.file_block_length = 0;    //初始化實際配置設定的磁盤号數組長度為0
            Directorys[i].fileDescriptor.fileLength = 0;           //初始化檔案長度為0
            Directorys[i].fileDescriptor.beginpos = 0;             //初始化檔案初始位置為0
            for (j = 0; j<Buffer_Length; j++){
                Directorys[i].fileDescriptor.RWBuffer[j] = '\0';   //初始化讀寫緩存為'\0'
            }
            Directorys[i].fileDescriptor.rwpointer = 0;            //初始化讀寫指針
        }
    }//for
    /*初始化位示圖,均初始化為空閑*/
    for (i = 0; i<map_row_num; i++){
        for (j = 0; j<map_cow_num; j++){
            if (i*map_cow_num + j<K)
                bitMap[i][j] = 1;      //K個保留區
            else
                bitMap[i][j] = 0;      //其餘區域空閑
        }//for
    }//for
}//Init
           

3.3 目錄

我們的檔案系統中僅設定一個目錄,該目錄包含檔案系統中的所有檔案。除了不需要顯示地建立和删除之外,目錄在很多方面和普通檔案相像。目錄對應0号檔案描述符。初始狀态下,目錄中沒有檔案,所有,目錄對應的描述符中記錄的長度應為0,而且也沒有配置設定磁盤塊。每建立一個檔案,目錄檔案的長度便增加一分。目錄檔案的内容由一系列的目錄項組成,其中每個目錄項由如下内容組成:

• 檔案名

• 檔案描述符序号

顯示目錄

/**
 * 函數名:show_Menu
 * 函數功能:提示菜單選項
 */
void show_Menu(){
    printf("==================菜單===================\n");
    printf("**   1.建立檔案\n");
    printf("**   2.檢視檔案清單\n");
    printf("**   3.檢視位圖資訊\n");
    printf("**   4.檢視硬碟使用情況\n");
    printf("**   5.删除檔案\n");
    printf("**   6.打開檔案\n");
    printf("**   7.關閉檔案\n");
    printf("**   8.移動檔案\n");
    printf("**   9.檢視檔案内容\n");
    printf("**   10.修改檔案内容\n");
    printf("**   11.檢視檔案詳細資訊\n");
    printf("**   0.退出\n");
    printf("=========================================\n");
}
           

3.4 檔案的建立與删除

建立檔案時需要進行如下操作;

• 找一個空閑檔案描述符(掃描ldisk [0]~ldisk [k - 1])

• 在檔案目錄裡為新建立的檔案配置設定一個目錄項(可能需要為目錄檔案配置設定新的磁盤塊)

• 在配置設定到的目錄項裡記錄檔案名及描述符編号.

• 傳回狀态資訊(如有無錯誤發生等)

删除檔案時需要進行如下操作(假設檔案沒有被打開):

• 在目錄裡搜尋該檔案的描述符編号

• 删除該檔案對應的目錄項并更新位圖

• 釋放檔案描述符

• 傳回狀态資訊

建立

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
/**
 * 函數名:create
 * 函數功能:根據指定的檔案名建立新檔案
 * @param filename
 * @return
 */
int create(char *filename){
    /*查詢該檔案是否存在*/
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            printf("該檔案已存在!\n");
            return ERROR;            //檔案存在
        }
    }
    /*檔案不存在,更新Directorys值*/
    int sub,i,j;
    //搜尋檔案清單,碰到第一個index=-1的值
    for (i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == -1){
            //Directorys[i]
            sub = i;    //找到一個可以用的位置
            break;
        }
        else if (i == maxDirectoryNumber){
            printf("空間不足!");
            return ERROR;
        }
    }
    /*為sub目錄項指派*/
    strcpy(Directorys[sub].fileName, filename);
    //更新index
    for (i = 1; i <= maxDirectoryNumber; i++){
        if (!isExist(i)){       //如果不存在編号為i的index值
            Directorys[sub].index = i;   //更新index值
            break;                    //更新結束
        }
    }
    /*輸入目錄項其他項*/
    printf("檔案大小 (< 61*512 Byte):");
    scanf("%d", &Directorys[sub].fileDescriptor.fileLength);
    //計算需要空間塊數量,用于判斷剩餘空間是否滿足要求
    int L_Counter;
    if (Directorys[sub].fileDescriptor.fileLength%B){
        L_Counter = Directorys[sub].fileDescriptor.fileLength / B + 1;
    }
    else{
        L_Counter = Directorys[sub].fileDescriptor.fileLength / B;
    }
    //查位示圖,找到沒使用的位置
    for (i = K; i<map_row_num*map_cow_num - L_Counter; i++){
        int outflag = 0;//标記位,用于跳出外循環
        //查找連續的L_Counter塊bitMap空間塊
        for (int j = 0; j<L_Counter; j++){
            int maprow = (i + j) / map_cow_num;
            int mapcow = (i + j) % map_cow_num;
            if (bitMap[maprow][mapcow]){//如果位圖某塊不空閑
                break;//進入外循環繼續查找
            }
            else{//位圖空閑
                if (j == L_Counter - 1){
                    outflag = 1;//找到可用塊,可以跳出查找
                }
            }
        }//for
        if (outflag == 1){
            //為塊數組指派,儲存資料
            Directorys[sub].fileDescriptor.file_block_length = L_Counter;
            //    printf("L_Counter=%d\n",L_Counter);
            Directorys[sub].fileDescriptor.beginpos = i;//i為起始位置(起始塊号)
            for (j = 0; j<L_Counter; j++){               //數組記錄占用的塊号
                Directorys[sub].fileDescriptor.file_allocation_blocknumber[j] = i + j;
            }
            //初始化其他項(應該可以省略)
            Directorys[sub].isOpenFlag = 0;
            Directorys[sub].fileDescriptor.rwpointer = 0;
            memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
            break;
        }
        else if (L_Counter + i == map_row_num*map_cow_num - 1 - K){
            printf("空間不足...x\n");
            Directorys[sub].index = -1;
            return ERROR;
        }
    }//for
    int map_ = i;
    printf(" %s create success!\n", filename);
    /*更新位示圖*/
    for (int j = 0; j<Directorys[sub].fileDescriptor.file_block_length; j++){//從i開始更新file_block_length的資料
        int maprow = (map_ + j) / map_cow_num;
        int mapcow = (map_ + j) % map_cow_num;
        bitMap[maprow][mapcow] = 1;
    }//for
    
    /*檔案建立結束*/
    Directorys[0].count++;          //更新檔案數量
    return OK;
}
           

删除

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
/**
 * 函數名:destroy
 * 函數功能:根據檔案名删除檔案
 * @param filename
 * @return
 */
int destroy(char *filename){
    int sub,i;
    for (i = 1; i <= maxDirectoryNumber; i++){//不是順序的
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到該檔案
        }
        else if (i == maxDirectoryNumber){
            printf("檔案不存在!\n");
            return ERROR;           //搜尋結束,未找到對應檔案名
        }
    }
    //    printf("%d\n",sub);
    //删除操作
    if (Directorys[sub].isOpenFlag){
        printf("檔案已打開,不可删除,請關閉後删除!\n");
        return ERROR;
    }
    /*更新位示圖資訊*/
    //位示圖為一個二維數組,記錄的是磁盤塊的橫坐标值,表示該塊磁盤是否空閑
    int position = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];   //起始磁盤号
    for (i = 0; i < Directorys[sub].fileDescriptor.file_block_length; i++){
        int d_row = (position + i) / map_row_num;
        int d_cow = (position + i) % map_row_num;
        bitMap[d_row][d_cow] = 0;
    }//指派空閑
    
    //更新Directorys[sub]資訊
    memset(Directorys[sub].fileName, '\0', File_Name_Length);//檔案名初始化
    Directorys[sub].index = -1;          //初始化檔案描述符序号為-1
    /*配置檔案描述符的相關項*/
    memset(Directorys[sub].fileDescriptor.file_allocation_blocknumber, -1, File_Block_Length);
    //初始化磁盤号數組為-1
    Directorys[sub].fileDescriptor.file_block_length = 0;    //初始化實際配置設定的磁盤号數組長度為0
    Directorys[sub].fileDescriptor.fileLength = 0;           //初始化檔案長度為0
    Directorys[sub].fileDescriptor.beginpos = 0;             //初始化檔案初始位置為0
    memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
    Directorys[sub].fileDescriptor.rwpointer = 0;            //初始化讀寫指針
    
    printf(" %s 删除成功!\n", filename);
    /*檔案數量處理*/
    Directorys[0].count--;
    return OK;
}
           

3.5 檔案的打開與關閉

檔案系統維護一張打開檔案表.打開檔案表的長度固定,其表目包含如下資訊:

• 讀寫緩沖區

• 讀寫指針

• 檔案描述符号

檔案被打開時,便在打開檔案表中為其配置設定一個表目;檔案被關閉時,其對應的表目被釋放。讀寫緩沖區的大小等于一個磁盤存儲塊。打開檔案時需要進行的操作如下:

• 搜尋目錄找到檔案對應的描述符編号

• 在打開檔案表中配置設定一個表目

• 在配置設定到的表目中把讀寫指針置為0,并記錄描述符編号

• 讀入檔案的第一塊到讀寫緩沖區中

• 傳回配置設定到的表目在打開檔案表中的索引号

關閉檔案時需要進行的操作如下:

• 把緩沖區的内容寫入磁盤

• 釋放該檔案在打開檔案表中對應的表目

• 傳回狀态資訊

打開

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
/**
 * 函數名:open
 * 函數功能:根據檔案名打開檔案。該函數傳回的索引号可用于後續的read, write, lseek, 或close 操作
 * @param filename
 * @return
 */
int open(char *filename){
    int sub;
    //查詢所有的目錄項
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到該檔案
        }
        else if (i == maxDirectoryNumber){
            return ERROR;           //搜尋結束,未找到對應檔案名
        }
    }
    Directorys[sub].isOpenFlag = 1;      //打開檔案标志
    return OK;
}//open
           

關閉

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
/**
 * 函數名:close
 * 函數功能:根據打開目錄索引号關閉指定檔案
 * @param index
 * @return
 */
int close(int index){
    int sub;                               //下角标,表示Directorys[sub]
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == index){
            sub = i;
            if (!Directorys[i].isOpenFlag){
                printf("檔案關閉!\n");
            }
            break;                          //找到
        }
        else if (i == maxDirectoryNumber){                     //是否為最後一個查詢的資料
            printf("索引資訊有誤\n");
            return ERROR;                   //index 資料有錯誤,找不到該索引
        }
    }//for
    //把緩沖區的内容寫入磁盤
    int pos = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];//縱坐标的起始位置
    for (int i = 0; i<Directorys[sub].fileDescriptor.fileLength; i++){
        int L_Pos = i / B;
        int B_Pos = i % B;
        ldisk[pos + L_Pos][B_Pos] = Directorys[sub].fileDescriptor.RWBuffer[i];
    }
    //釋放該檔案在打開檔案表中對應的表目
    Directorys[sub].isOpenFlag = 0;  //釋放,标志位置零
    Directorys[sub].fileDescriptor.rwpointer = 0;//讀寫指針清除
    //傳回狀态資訊
    return OK;
}//close
           

3.6 讀寫

檔案打開之後才能進行讀寫操作.讀操作需要完成的任務如下:

1. 計算讀寫指針對應的位置在讀寫緩沖區中的偏移

2. 把緩沖區中的内容拷貝到指定的記憶體位置,直到發生下列事件之一:

• 到達檔案尾或者已經拷貝了指定的位元組數。這時,更新讀寫指針并傳回相應資訊

• 到達緩沖區末尾。這時,把緩沖區内容寫入磁盤,然後把檔案下一塊的内容讀入磁盤。最後傳回第2步。

/**
 * 函數名:read
 * 函數功能:從指定檔案順序讀入count 個位元組memarea 指定的記憶體位置。讀操作從檔案的讀寫指針訓示的位置開始
 * @param index
 * @param mem_area
 * @param count
 * @return
 */
int read(int index, char memory_area[], int count){
    int sub = isExist(index);
    if (sub == ERROR){
        printf("索引資訊有誤 !\n");
        return ERROR;
    }
    /*找到檔案*/
    /*打開檔案進行操作*/
    if (!Directorys[sub].isOpenFlag){
        open(Directorys[sub].fileName);
    }
    /*讀ldisk内容并複制到memory_area[]中*/
    int step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[0];
    //L的起始位置
    int step_ = Directorys[sub].fileDescriptor.file_block_length - 1;     //記錄要拷貝塊的數量
    /*将檔案以B為大小劃分後拷貝給mem_area[]*/
    int pos = 0;
    for (int i = 0; i<step_; i++){
        load(step_L, B, pos, memory_area);
        pos += B;
        step_L++;
    }
    /*拷貝ldisk[][]最後一塊資料*/
    int strLen = Directorys[sub].fileDescriptor.fileLength - (B*step_);
    load(step_L, strLen, pos, memory_area);
    //printf("檔案:%c\n", memory_area[1]);
    //注:配置設定的檔案大小不是真正拷貝的檔案大小
    return OK;
}
           

/**
 * 函數名:write
 * 函數功能:把memarea 指定的記憶體位置開始的count 個位元組順序寫入指定檔案。寫操作從檔案的讀寫指針訓示的位置開始
 * @param index
 * @param mem_area
 * @param count
 * @return
 */
int write(int index, char memory_area[], int count){
    /*根據index找到檔案*/
    int sub = isExist(index);
    if (sub == ERROR){
        printf("索引資訊有誤!\n");
        return ERROR;
    }
    /*找到檔案*/
    /*打開檔案進行操作*/
    if (!Directorys[sub].isOpenFlag){
        open(Directorys[sub].fileName);
    }
    /*讀入要寫的内容*/
    int i = 0;
    int step_ = 0;//file_allocation_blocknumber[]下标計數器
    int num = 0;//RWBuffer[]讀寫次數計數器
    int step_L;
    int step_B;
    int COUNT = count;
    while (count){
        Directorys[sub].fileDescriptor.RWBuffer[i] = memory_area[COUNT - count];
        count--;//count計數遞減
        i++;//計數+1
        if (i == Buffer_Length){
            int step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[step_];
            //列坐标
            int step_B = Buffer_Length * num;
            save(step_L, step_B, Buffer_Length, sub);//複制完成
            num++;
            if (num == B / Buffer_Length){//寫完一行,進入下一行
                num = 0;
                step_++;
            }
            i = 0;
            //
        }
        if (count == 0){
            step_L = Directorys[sub].fileDescriptor.file_allocation_blocknumber[step_];
            step_B = Buffer_Length * num;
            save(step_L, step_B, i, sub);
            break;
        }
    }//while
    memset(Directorys[sub].fileDescriptor.RWBuffer, '\0', Buffer_Length);
    return OK;
}
           

3.7 檔案清單

/**
 * 函數名:directory
 * 函數功能:清單顯示所有檔案及其長度
 */
void directory(){
    if (Directorys[0].count == 0) {
        printf("無檔案\n");
    }
    for (int i = 1; i <= Directorys[0].count; i++){
        if (Directorys[i].index != -1){            //index值有效的檔案輸出
            printf(" %d :%s\t\t", i, Directorys[i].fileName);
            printf("大小:%d Byte\n", Directorys[i].fileDescriptor.fileLength);
        }//
    }
}//directory
           

3.8磁盤資訊顯示

/**
 * 函數名:show_ldisk
 * 函數功能:顯示磁盤資訊
 */
void show_ldisk(){
    for (int i = 0; i<L; i++){
        printf("%d:", i);
        printf("%s\n", ldisk[i]);
    }
    printf("\n");
}
           

3.9檔案詳細資訊檢視

/**
 * 函數名:show_File
 * 函數功能:顯示檔案資訊
 * @param filename
 * @return
 */
int show_File(char *filename){
    int sub;
    //查詢所有的目錄項
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (strcmp(Directorys[i].fileName, filename) == 0){
            sub = i;
            break;                 //找到該檔案
        }
        else if (i == maxDirectoryNumber){
            return ERROR;           //搜尋結束,未找到對應檔案名
        }
    }
    printf("檔案名:%s\n", Directorys[sub].fileName);
    printf("是否打開 (Y:0 N:1):%d\n", Directorys[sub].isOpenFlag);
    //printf("index: %d\n", Directorys[sub].index);
    printf("大小:%d Byte\n", Directorys[sub].fileDescriptor.fileLength);
    return OK;
}
           

3.10位圖資訊

/**
 * 函數名:show_bitMap
 * 函數功能:顯示位圖資訊
 */
void show_bitMap(){
    for (int i = 0; i<map_row_num; i++){
        for (int j = 0; j<map_cow_num; j++){
            printf("%d  ", bitMap[i][j]);
        }
        printf("\n");
    }//for
}//show_bitMap
           

3.11檔案移動

/**
 * 函數名:lseek
 * 函數功能:把檔案的讀寫指針移動到pos 指定的位置
 * @param index
 * @param pos
 * @return
 */
int lseek(int index, int position){
    //先找到index代表的資料項
    int sub;                               //下角标,表示Directorys[sub]
    for (int i = 1; i <= maxDirectoryNumber; i++){
        if (Directorys[i].index == index){
            sub = i;
            break;                          //找到
        }
        else if (i == maxDirectoryNumber){                  //是否為最後一個查詢的資料
            printf("索引資訊有誤!\n");
            return ERROR;                   //index 資料有錯誤,找不到該索引
        }
    }//for
    //找到index對應的元素後,把檔案的讀寫指針移動到position 指定的位置
    Directorys[sub].fileDescriptor.rwpointer = position;
    return OK;                              //處理成功
}//lseek
           

4 測試

為了能夠對我們的模拟系統進行測試,請編寫一個操縱檔案系統的外殼程式或者一個菜單驅動系統。

4.1 菜單

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.2 建立檔案

檔案不存在

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

檔案存在時

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.3 檢視檔案清單

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.4 檢視位圖資訊

儲存檔案前

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

儲存3個檔案後

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.5 打開/關閉檔案

打開檔案 1.txt 與檔案 2.txt

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

關閉檔案 2.txt

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.6 删除檔案

若檔案已打開,則不可删除

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

若檔案處于關閉狀态,則順利删除

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

删除成功

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.7 移動檔案

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.8 檢視/修改檔案内容

檢視檔案 1.txt :無内容

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

修改檔案 1.txt :

若大于檔案大小,則不儲存

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

檢視檔案 1.txt :無儲存的内容

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

若小于檔案大小,則儲存成功

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

再次檢視檔案 1.txt :有儲存的内容

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.9 檢視檔案詳情

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 
作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

4.10 檢視磁盤存儲情況(512*64)

作業系統實驗——檔案作業系統1 實驗簡介2 I/O系統3 檔案系統4 測試5 總結 

使用情況截圖(部分)

5 總結 

在這次設計中,我對于檔案屬性,檔案命名,檔案操作,檔案存取方式有了更加深刻的了解,其中令我印象最為深刻的是檔案目錄的管理。其中的檔案控制塊跟索引節點起到了非常重要的作用。檔案控制塊中包含了有關檔案存取控制的資訊,檔案結構的資訊,檔案使用的資訊,檔案管理的資訊。查找檔案時,根據檔案名找到檔案控制塊,再通過控制塊獲得相應的資訊。

為了減少檢索檔案通路的實體快熟,檔案系統把檔案目錄項中的檔案名和其他管理資訊分開。後者單獨組成定長的一個資料結構,稱為索引節點。

本次實驗時間較短,有諸多不完善之處,未來有時間講進行總結及完善,另外還需要多借鑒他人檔案系統的整體設計方式和思想,對檔案系統有了一個比較全面深刻的認識。