1. 程式人生 > >[作業系統實踐][簡單的檔案系統]

[作業系統實踐][簡單的檔案系統]

簡單檔案系統的實現

要求

  • 記憶體中開闢一塊虛擬磁碟空間作為檔案儲存分割槽,在其上實現一個簡單的基於多級目錄單使用者單任務系統中的檔案系統。

  • 在退出該檔案系統的使用時,虛擬檔案系統以一個檔案的方式儲存到磁碟中,以便下次可以把它恢復到記憶體的虛擬儲存空間

實際實現

  • 以上兩點均實現
  • 能處理絕對路徑和相對路徑的命令

    • 例如 :
      • cd /home/zy/Desktop/ 這樣的絕對路徑
      • cd ../hah/1/2 這樣的相對路徑
    • mkdir,rmdir,cd,creat,rm均支援
    • open_pathopen的升級版,也是支援上述函式實現的主要函式。
  • 包裝open,read,close

    實現了一個cat直接列印檔案內容。

    • 檢查檔案是否開啟,如果打開了直接進行下一步,沒有就開啟
    • read出所有內容
    • 如果之前不是開啟的那麼就關閉檔案。

截圖

  • 建立目錄樹,/home是使用者的根目錄

    /home下有/zy

    /zy下有 /Documents,/Desktop,/Viedeos,Music

  • /home/zy/Documents目錄下建立一個檔案Hello.txt

    • 並輸入內容Hello World!Fisrt,能正確顯示長度和檔案內容。
    • 測試了creat,open,closeread,write等基本用法

  • 利用creat /home/zy/hellozy.txt/home/zy下建立了一個hellozy.txt

    • 測試了creat路徑下的用法

  • 測試了mkdir,cd,rmdir在路徑下也能正常工作。其餘幾個類似的同理,OVER

可以改進的地方

  • 有一些BUG還待處理
  • 完善異常處理機制
  • 完善檔案資訊,包括建立時間,修改時間。
  • 嘗試實現多工的檔案系統。

以下程式碼並非最終版本,之後還略有修改,詳細程式碼存放在github

OS.h

幾個常量定義

#include <cstdio>
#include <memory.h>
#include <string>
#include <iostream>
#include <malloc.h>
#include <time.h>
using namespace std;
/*常量定義*/
#define  Path  "/home" //根目錄
#define BLOCKSIZE  1024 //磁碟塊大小
#define BLOCKCOUNT  1000 //盤塊大小
#define MAXOPENFILE 10       //能開啟最多的檔案數
#define DISKSIZE  (BLOCKSIZE*BLOCKCOUNT)//磁碟大小
#define END -1
const int FCBCOUNT = BLOCKSIZE/sizeof(FCB);//一個塊的最多FCB數量

DISK,DirFile,USEROPEN,FCB定義

DISK定義

  • 總共1000個磁碟塊
    • FAT1:4個
    • FAT2:4個
    • 根目錄 1個
    • 其餘資料 991個

程式碼:

/*------------------磁碟------------------------*/
struct DISK
{
    int FAT1[BLOCKCOUNT];//磁碟塊0-3代表FAT
    int FAT2[BLOCKCOUNT];//磁碟塊4-7代表FAT2
    DirFile RootDir;    //根目錄 磁碟塊8
    char Data[BLOCKCOUNT-9][BLOCKSIZE];//目錄和其他檔案 磁碟塊9~1000
};

DirFile 定義

程式碼:

/*-----------------目錄檔案---------------------*/
struct DirFile{
    FCB fcb[FCBCOUNT];  //檔案控制塊
    void init(int father,int self)
    {
        //給根目錄建立.. 和 .  序號0放".", 序號1放".."
        memset(fcb,0,sizeof(fcb));
        fcb[1].free=fcb[0].free=1;
        fcb[1].attribute=fcb[0].attribute=1;
        fcb[1].first=father;
        fcb[0].first=self;
        memcpy(fcb[0].filename,".",sizeof("."));
        memcpy(fcb[1].filename,"..",sizeof(".."));
    }
};

FCB

struct FCB
{
    char filename[12]; //檔名
    char attribute;//0表示目錄,1表示資料檔案
    int time;//建立時間
    int data;//建立日期
    int first;//起始盤號
    int length;//長度
    char free;//表示目錄項是否為空
};

USEROPEN

struct USEROPEN
{
    FCB fcb;
    char dir[80];//相應開啟檔案所在的目錄名
    int count;//讀寫指標在檔案的位置
    char fcbstate;//是否修改了檔案的FCB內容,修改了置為1,否則置為0
    char topenfile;//表示該使用者表項是否被佔用,1就是被佔用,0就是沒有被佔用
    char fatherfilename[12];//上一層目錄的名字
    int pos;
};

main.cpp

解析

  • 全域性變數的宣告
  • 簡單的處理命令列的讀入。
  • ls函式

程式碼

#include "OS.h"
using namespace std;

/*-------------函式宣告------------------------*/
void help();

int cd(char *dirname);

int startsys();

int format();

int mkdir(char *dirname);

int rmdir(char *dirname);

int close(int fd);

int open(char *filename);

int creat(char *filename);

int rm(char *filename);

int filewrite(int fd);

int dowrite(int fd,char *text,int len, char wstyle);

int fileread(int fd,int len);

int doread(int fd,int len,char *text);

void exitsys();
/*--------------全域性變數-------------------------*/
char* myvhard;//虛擬磁碟起始地址
string currentdir="/home";//當前目錄
string cmd; //讀取指令
USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
DISK* disk;//將內容結構化
char command[50];//檔名標示符




/*--------------------- 顯示目錄函式 ---------------*/
void ls() {
    int BlockDirNum = (ptrcuridr->fcb).first;
    DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8];
    for (int i = 0; i < FCBCOUNT; i++) {
        if (dir->fcb[i].free == 1) {
            if (dir->fcb[i].attribute == 0)
                printf("%10s---length:%5d----File\n",dir->fcb[i].filename,dir->fcb[i].length);
            else
                printf("%10s---length:%5d----Directory\n",dir->fcb[i].filename,dir->fcb[i].length);
        }
    }
}



int main() {
    printf("Welcome the OS FileSystem\n");
    printf("input 'help' get more information\n\n\n");
   // freopen("E:\\OSFileSystem\\a.in","r",stdin);
    startsys(); //Init the System
    int len;
    while(1)
    {
        cout<<currentdir+">";
        cin>>cmd;
        if(cmd=="help"){            //幫助
            help();
        }
        else if(cmd=="mkdir"){
            cin>>command;
            mkdir(command);
        }
        else if(cmd=="cd"){
            cin>>command;
            cd(command);
        }
        else if(cmd=="exit") {
            break;
        }
        else if(cmd=="rmdir"){
            cin>>command;
            rmdir(command);
        }
        else if(cmd=="ls"){
            ls();
        }
        else if(cmd=="open"){
            cin>>command;
            open(command);
        }
        else if(cmd=="close"){
            cin>>command;
            close(atoi(command));
        }
        else if(cmd=="creat"){
            cin>>command;
            creat(command);
        }
        else if(cmd=="rm"){
            cin>>command;
            rm(command);
        }
            //
        else if(cmd=="write"){
            cin>>command;
            filewrite(atoi(command));
        }
        else if(cmd=="read") {
            cin >> command >> len;
            fileread(atoi(command),len);
        }
        else if(cmd=="exitsys"){
            exitsys();
        }else {
            printf("The cmd is not exits\n");
        }
    }
}

startsys.cpp

分析

  • int format()
    • 分配磁碟空間
    • 初始化根目錄
      • 加入...兩個子目錄
  • int startsys()
    • 申請磁碟空間
    • 載入之前的磁碟,如果沒有就申請。
    • 把根目錄載入進檔案開啟表。

程式碼

#include "OS.h"
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符
/*--------------------------------磁碟格式化函式-------------------*/
int format() {
    memset(myvhard,0,DISKSIZE);
    //建立根目錄,在磁碟塊8

    //前九個被FAT1+FAT2+root佔用
    for(int i=0;i<9;i++){
        disk->FAT1[i]=disk->FAT2[i]=-2;//-2代表被佔用
    }
    DirFile *dir=(DirFile *)disk->Data[8-8];//注意Data和FAT的區別
    //初始化根目錄.
    dir->init(8,8);
    return 1;
}


/*--------------------------------進入檔案系統函式--------------------*/
int startsys() {
    myvhard=(char *)malloc(DISKSIZE);   //申請1024*1000磁碟空間
    disk=(DISK *)myvhard;
    FILE *fp=fopen("myfsys","r");
    if(fp!=NULL)
    {
        printf("|-------------------------------------------|\n");
        printf("|-----------myfsys is loading---------------|\n");
        printf("|-------------------------------------------|\n\n");
        fread(myvhard,sizeof(char),DISKSIZE,fp);
        fclose(fp);
    }
    else{
        printf("|-------------------------------------------|\n");
        printf("|-----------myfsys is not exit--------------|\n");
        printf("|--File system is being created now --------|\n");
        printf("|-------------------------------------------|\n\n");
        format();
    }
    //初始化使用者開啟表
    memset(openfilelist,0,sizeof(openfilelist));
    //將根目錄開啟,首先修改fcb裡的內容
    openfilelist->fcb.first=8;
    //檔案開啟表項的內容
    openfilelist[0].topenfile=1;
    strcpy(openfilelist->dir,"");
    strcpy(openfilelist->fcb.filename,"home");
    strcpy(openfilelist->fatherfilename,"");
    ptrcuridr=&openfilelist[0];
    openfilelist[0].pos=0;
    //當前目錄設定為根目錄
    currentdir=Path;
    return 1;
}

OPEN.CPP

分析

  • 處理好...兩個子目錄

  • 維護好openfilelist裡的每個值

程式碼

#include "OS.h"

/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符

/*-----------------------------開啟檔案函式--------------------*/
int open(char *filename){

    //檢查要被開啟檔案是否存在
    int BlockDirNum = (ptrcuridr->fcb).first;
    DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8];
    int Fileaddr = -1;
    for (int i = 0; i < FCBCOUNT; i++) {
        if (dir->fcb[i].free == 1 && strcmp(dir->fcb[i].filename, filename) == 0)//表項被使用,且是目錄,且檔名相等
        {
            Fileaddr = i;//檔案存在
            break;
        }
    }
    //檔案不存在 輸出-1
    if(Fileaddr==-1){
        printf("file does not exist\n");
        return -1;
    }

    //檢查開啟檔案表是否還有空表項,沒有報錯,有則記錄
    int OpenFileaddr=-1;
    for(int i=0;i<MAXOPENFILE;i++) {
        if (openfilelist[i].topenfile == 0) {
            OpenFileaddr=i;
        }
    }
    //沒有空表了
    if(OpenFileaddr==-1) {
        printf("File open table is full \n");
        return -1;
    }
    //如果又要開啟一個根目錄,那麼直接返回0
    if(dir->fcb[Fileaddr].first==8)
    {
        OpenFileaddr=0;
        if(ptrcuridr->fcb.first==8)
            return 0;
    }
    //為該檔案填寫檔案開啟表項

    //檢查是否已經開啟
    //需要一個temp來表示實際的dir值
    char temp[300];
    if(strcmp(filename,"..")==0)
    {
        strcpy(temp,ptrcuridr->dir);
        int len1=strlen(ptrcuridr->dir);
        int len2=strlen(ptrcuridr->fatherfilename);
        temp[len1-len2-1]=0;
    }
    else
    {
        char buffer[80];
        memset(buffer,0,sizeof(buffer));
        strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename);
        strcpy(temp,buffer);
    }
    for(int i=1;i<MAXOPENFILE;i++) {
        //"."一定是被打開了
        if ((openfilelist[i].topenfile == 1 && strcmp(openfilelist[i].fcb.filename, filename) == 0 &&
             strcmp(openfilelist[i].dir,temp) ==0 )||(strcmp(filename,".")==0))
             {
            printf(" The file has been opened !\n");
            return -1;//無效返回-1
        }
    }
    if(strcmp(filename,"..")==0)
    {
        openfilelist[OpenFileaddr].fcb=dir->fcb[Fileaddr];
        //名字是錯的,會是"..";正確的名字在工作塊的父親名字
        strcpy(openfilelist[OpenFileaddr].fcb.filename,ptrcuridr->fatherfilename);
        //曾經的路徑減去名字減去'/' 就是新的
        strcpy(openfilelist[OpenFileaddr].dir,ptrcuridr->dir);
        int len1=strlen(openfilelist[OpenFileaddr].dir);
        int len2=strlen(ptrcuridr->fatherfilename);
        openfilelist[OpenFileaddr].dir[len1-len2-1]=0;
        //找新的fathername,通過分析dir來得到
        char test[20];
        strcpy(test,openfilelist[OpenFileaddr].dir);
        char *q;
        int len=strlen(test);
        for(int i=0;i<len;i++)
        {
            if(test[i]=='/'&&i!=len-1)
                q=test+i+1;
        }
        strcpy(openfilelist[OpenFileaddr].fatherfilename,q);
    }
    else
    {
        openfilelist[OpenFileaddr].fcb=dir->fcb[Fileaddr];
        char buffer[80];
        memset(buffer,0,sizeof(buffer));
        strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename);
        strcpy(openfilelist[OpenFileaddr].dir,buffer);
        strcpy(openfilelist[OpenFileaddr].fatherfilename,ptrcuridr->fcb.filename);
    }
    openfilelist[OpenFileaddr].pos=OpenFileaddr;
    openfilelist[OpenFileaddr].count=0;
    openfilelist[OpenFileaddr].fcbstate=0;
    openfilelist[OpenFileaddr].topenfile=1;
    //返回檔案描述符fd,此時的fd跟下標相同,一般不同.
    if(openfilelist[OpenFileaddr].fcb.attribute==0)//如果是檔案,輸出檔案開啟符號
        printf("File Open Success,The fd is %d\n",OpenFileaddr);
    return OpenFileaddr;
}

OPEN_PATH.CPP

分析

  • 讓系統函式都能處理絕對路徑相對路徑,而不僅僅是當前目錄下的檔案了。

    • cd,mkdir,creaet,rm,rmdir
  • 使用的方式是拆分路徑的元素,然後分析元素

    不斷的呼叫openclose來實現。

程式碼

#include "OS.h"
int open(char *filename);
int close(int fd);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符

/*----------------------更改當前目錄函式---------------------

讀入一條檔案路徑,返回一個開啟的fd

 支援絕對路徑和相對路徑.

 輸出,如果路徑正確,返回檔案開啟後的fd.

------------------------------------------------------*/
int open_path(char *dirname) {
    //如果dirname是絕對路徑
    int fd=0, ok = 1, fdtemp = -1;//ok代表是否找到dirname所指的檔案,fdtemp存臨時的,用來關閉
    USEROPEN *temp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯

    if (dirname[0] == '/') {
        ptrcuridr = openfilelist;//我們的openfilelist[0]永遠是根目錄
        //使工作目錄暫時指向根目錄
        char *p = strtok(dirname + 1, "/");//用“/”分割 dirname[1]開始的字串
        if (p != NULL) p = strtok(NULL, "/");//跳過/home
        while (p) {
            fd = open(p);
            if (fd == -1) {
                ok = 0;
                if (fdtemp != -1)  //離開前記得關檔案
                    close(fdtemp);//把上個開啟的檔案關掉
                break;
            }
            ptrcuridr = openfilelist + fd;
            if (fdtemp != -1)
                close(fdtemp);//把上個開啟的檔案關掉
            fdtemp = fd;
            p = strtok(NULL, "/");
        }
    }
        //如果是相對路徑
    else {
        int len=strlen(dirname);
        dirname[len]='/';
        dirname[len+1]=0;
        char *p = strtok(dirname, "/");//用“/”分割 dirname[1]開始的字串
        while (p) {
            fd = open(p);
            if (fd == -1) {
                ok = 0;
                if (fdtemp != -1)  //離開前記得關檔案
                    close(fdtemp);//把上個開啟的檔案關掉
                break;
            }
            ptrcuridr = openfilelist + fd;
            if (fdtemp != -1)
                close(fdtemp);//把上個開啟的檔案關掉
            fdtemp = fd;
            p = strtok(NULL, "/");
        }
    }
         ptrcuridr = temp;
        //輸出資料
        if (ok == 1)
            return fd;
        else
            return -1;

}

close.cpp

分析

  • 記得把檔案開啟表的東西儲存

程式碼

#include "OS.h"
int open_path(char* dirname);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符

/*---------------關閉檔案函式-----------------*/
int close(int fd){
    //檢查fd的合法性
    if(fd>=MAXOPENFILE||fd<=0){
        printf(" Is not a legitimate fd \n");
        return -1;
    }else if(openfilelist[fd].topenfile==0){
        printf("filewrite ERROR:The File Don't Open\n");
        return -1;
    }

    //檢查使用者開啟檔案表表項的`fcbstate`欄位,如果是1,則需要將該檔案的FCB的內容儲存的虛擬磁碟上該檔案的目錄項
    //方法是:開啟該檔案的父目錄檔案,已覆蓋寫方式呼叫do_wirte()將欲關閉的FCB寫入父目錄檔案的相應盤塊.
    if(openfilelist[fd].fcbstate==1){
        char buffer[30]="..";
         int fatherfd=open_path(buffer);
        if(fatherfd!=-1) {
            //找到相應的盤號
            int pan1 = openfilelist[fatherfd].fcb.first;
            int area1 = -1;
            //盤號上相應的位置
            DirFile *dirson = (DirFile *) (disk->Data[pan1 - 8]);
            for (int i = 0; i < FCBCOUNT; i++) {
                if (dirson->fcb[i].free == 1  &&
                    strcmp(dirson->fcb[i].filename, openfilelist[fd].fcb.filename) == 0) {
                    //找到了該檔案,覆蓋fcb
                    dirson->fcb[i] = openfilelist[fd].fcb;
                    break;
                }
            }
            //關檔案
            if(fatherfd!=0)
            close(fatherfd);
        }
    }
    //回收該檔案佔據的使用者開啟表表項(clear),topenfile欄位置0
    memset(openfilelist+fd,0,sizeof(openfilelist[0]));
    openfilelist[fd].topenfile=0;
    //返回
    return 0;
}

mkdir.cpp

分析

  • 利用open_path來返開啟一個父級目錄,並返回fd
  • 將當前工作目錄ptrcuridr的原始值儲存下來,然後將其賦值給那個父級目錄。
  • 最後還原ptrcuridr

程式碼

#include "OS.h"
int close(int fd);
int open_path(char *dirname);
int FileSubstr(char *str);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符




int mkdir(char *dirname)
{
    char newdir[20];
    char dirpath[60];
    USEROPEN *tempp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯
    int k=FileSubstr(dirname),fd=-1;
    if(k!=-1) {
        dirname[k] = 0;
        memset(newdir, 0, sizeof(newdir));
        memset(dirpath, 0, sizeof(dirpath));
        strcpy(newdir, dirname + k + 1);
        strcpy(dirpath, dirname);
        fd = open_path(dirpath);
        if(fd!=-1) {
            ptrcuridr = openfilelist + fd;
            dirname = newdir;
        }
        else {
            printf("error\n");
            return -1;
        }
        }


    //-------------以下為一天前的程式碼-----------------------//
    //讀取當前目錄的地址
    int BlockDirNum=(ptrcuridr->fcb).first;
    DirFile *dir=(DirFile *)disk->Data[BlockDirNum-8];
    //遍歷檔案目錄,檢查是否有檔名相同的檔案或目錄,並找一個沒有被使用的目錄空閒表項
    int temp=-1, DirFreeItems =-1;
    for(int i=0;i<FCBCOUNT;i++) {
        if (dir->fcb[i].free == 1 && strcmp(dir->fcb[i].filename, dirname) == 0)//表項被使用,且是目錄,且檔名相等
        {
            temp = i;//重名的表項
            break;
        }
        else if (dir->fcb[i].free == 0) {
            DirFreeItems = i;//目錄空閒表項
        }
    }
    //如果檔名已存在,報錯並退出
    if(temp!=-1)
    {
        printf("mkdir: cannot create directory '%s': Directory exists\n",dirname);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //如果沒有空閒位置,報錯退出
    if(DirFreeItems==-1)
    {
        printf("mkdir: cannot create directory '%s': Directory is full \n",dirname);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //檢查FAT中是否有空閒的盤塊
    int FATFreeItems=-1;
    for(int i = 0;i < BLOCKCOUNT;i++)
    {
        if(disk->FAT1[i] == 0) {//沒被使用的塊標記為0
            FATFreeItems=i;//找到了一個空閒塊
            break;
        }
    }
    //如果FAT沒有空閒塊,報錯退出
    if(FATFreeItems==-1)
    {
        printf("mkdir: cannot create directory '%s': Disk is full \n",dirname);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    /*----------------開始新建目錄-------------------*/
    //修改長度,fcbstate置為1
    ptrcuridr->fcbstate=1;
    ptrcuridr->fcb.length++;//不包括.和..的
    //分配FAT的空閒塊,2表示被目錄使用
    disk->FAT1[FATFreeItems]=disk->FAT2[FATFreeItems]=2;
    //將改塊分配到 當前目錄的空閒專案下
    strcpy(dir->fcb[DirFreeItems].filename,dirname);
    dir->fcb[DirFreeItems].free=1;//被使用
    dir->fcb[DirFreeItems].attribute=1;//是目錄
    dir->fcb[DirFreeItems].first=FATFreeItems;//分配FAT空閒塊
    dir->fcb[DirFreeItems].length=0;
    dir->fcb[DirFreeItems].data=0;//時間之後弄
    dir->fcb[DirFreeItems].time=0;//時間之後弄
    //進入下一次目錄,初始化新獲得的塊(重置給予"."和"..")
    dir=(DirFile*)(disk->Data[FATFreeItems-8]);
    dir->init(BlockDirNum,FATFreeItems);
    /*----------------恢復現場------------------------*/
    if(fd!=-1)
      close(fd);
    ptrcuridr=tempp;
    return 1;
}

rmdir.cpp

分析

  • mkdir類似

程式碼

#include "OS.h"
int close(int fd);
int open_path(char *dirname);
int FileSubstr(char *str);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符
/*-------------------------------刪除子目錄函式---------------------*/
int rmdir(char *dirname) {

    char newdir[20];
    char dirpath[60];
    USEROPEN *tempp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯
    int k=FileSubstr(dirname),fd=-1;
    if(k!=-1) {
        dirname[k] = 0;
        memset(newdir, 0, sizeof(newdir));
        memset(dirpath, 0, sizeof(dirpath));
        strcpy(newdir, dirname + k + 1);
        strcpy(dirpath, dirname);
        fd = open_path(dirpath);
        if(fd!=-1) {
            ptrcuridr = openfilelist + fd;
            dirname = newdir;
        }
        else {
            printf("error\n");
            return -1;
        }
    }



    /*---------使用open_path更新----------------------*/
    //檢查檔案是否存在
    int BlockDirNum = (ptrcuridr->fcb).first;
    DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8];
    int temp = -1;
    for (int i = 0; i < FCBCOUNT; i++) {
        if (dir->fcb[i].free == 1 && dir->fcb[i].attribute == 1 &&
            strcmp(dir->fcb[i].filename, dirname) == 0)//表項被使用,且是目錄,且檔名相等
        {
            temp = i;//檔案存在
            break;
        }
    }
    //要刪除的目錄不存在
    if(temp == -1) {
        printf("rmdir: failed to remove '%s': No such file or directory\n",dirname);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //判斷子目錄是否為空,不包括0和1,也可以用length,懶得用
    DirFile *dirson=(DirFile*)(disk->Data[dir->fcb[temp].first-8]);
    int flag=-1;
    for(int i=2; i < FCBCOUNT; i++ ) {
        if (dir->fcb[i].free == 1){
            flag=1;
            break;
        }
    }
    //要刪除的目錄不為空
    if(flag==-1)
    {
        printf("rmdir: failed to remove '%s': Directory not empty\n",dirname);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //檢查目錄是否已開啟,開啟就關閉
    //回收該目錄檔案所佔據的磁碟塊,修改FAT
    disk->FAT1[dir->fcb[temp].first]=disk->FAT1[dir->fcb[temp].first]=0;
    //當前目錄檔案中清空該目錄檔案的目錄項,memset清理乾淨
    memset(&(dir->fcb[temp]),0,sizeof(dir->fcb[temp]));
    //修改長度,表項的fcbstate置為1
    ptrcuridr->fcbstate=1;
    ptrcuridr->fcb.length--;//不包括.和..的
    /*-----------------恢復現場-------------*/
    if(fd!=-1)
        close(fd);
    ptrcuridr=tempp;
    return 1;
}

cd.cpp

分析

  • 善於利用open_path十分簡單的實現一個跳轉到任意路徑的函式

程式碼

#include "OS.h"
int open(char *filename);
int close(int fd);
int open_path(char *dirname);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符

/*----------------------更改當前目錄函式---------------------*/
int cd(char *dirname) {
        USEROPEN *temp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯
        int fd=open_path(dirname);
        if (fd != -1) {
            //關掉舊的描述符
           int old=temp->pos;
            //獲取舊的描述符
            if (old != 0)   //根目錄描述符不關
                close(old);
            //工作目錄指向它
            ptrcuridr = openfilelist + fd;
            //當前目錄賦值
            currentdir= ptrcuridr->dir ;
            currentdir+= '/';
            currentdir+= ptrcuridr->fcb.filename;
            return 0;
        }
        else {
            ptrcuridr = temp;
            printf("No such file or directory\n");
            return 0;
        }
    }

檔案操作

creat.cpp

分析

  • 有了open_path so easy

程式碼

#include "OS.h"
int close(int fd);
int open_path(char *dirname);
int FileSubstr(char *str);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符


int creat(char *filename){
    //為新檔案分配一個空閒開啟檔案表項,如果沒有空閒表項就返回 -1
    //檢查開啟檔案表是否還有空表項,沒有報錯,有則記錄
    int OpenFileaddr=-1;
    for(int i=0;i<MAXOPENFILE;i++) {
        if (openfilelist[i].topenfile == 0) {
            OpenFileaddr=i;
        }
    }
    //沒有空表了
    if(OpenFileaddr==-1) {
        printf("File open table is full \n");
        return -1;
    }
    /*-----------開啟路徑所指的父目錄---------*/
    char newdir[20];
    char dirpath[60];
    USEROPEN *tempp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯
    int k=FileSubstr(filename),fd=-1;
    if(k!=-1) {
        filename[k] = 0;
        memset(newdir, 0, sizeof(newdir));
        memset(dirpath, 0, sizeof(dirpath));
        strcpy(newdir, filename + k + 1);
        strcpy(dirpath, filename);
        fd = open_path(dirpath);
        if(fd!=-1) {
            ptrcuridr = openfilelist + fd;
            filename = newdir;
        }
        else {
            printf("error\n");
            return -1;
        }
    }
    //檢查重名
    int BlockDirNum = (ptrcuridr->fcb).first;
    DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8];
    int temp = -1,DirFreeItems =-1;
    for (int i = 0; i < FCBCOUNT; i++) {
        if (dir->fcb[i].free == 1  &&
            strcmp(dir->fcb[i].filename, filename) == 0)//表項被使用,且是目錄,且檔名相等
        {
            temp = i;//有重名,可能檔案,可能資料夾
            break;
        }
        else if (dir->fcb[i].free == 0) {
            DirFreeItems = i;//目錄空閒表項
        }
    }
    //如果檔名已存在,報錯並退出
    if(temp!=-1)
    {
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        printf("creat: cannot create file '%s': File exists\n",filename);
        return 0;
    }
    //如果沒有空閒位置,報錯退出
    if(DirFreeItems==-1)
    {
        printf("creat: cannot create file '%s': Directory is full \n",filename);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //檢查FAT中是否有空閒的盤塊
    int FATFreeItems=-1;
    for(int i = 0;i < BLOCKCOUNT;i++)
    {
        if(disk->FAT1[i] == 0) {//沒被使用的塊標記為0
            FATFreeItems=i;//找到了一個空閒塊
            break;
        }
    }
    //如果FAT沒有空閒塊,報錯退出
    if(FATFreeItems==-1)
    {
        printf("mkdir: cannot create directory '%s': Disk is full \n",filename);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    /*----------------開始新建檔案-------------------*/
    //修改長度,fcbstate置為1
    ptrcuridr->fcbstate=1;
    ptrcuridr->fcb.length++;//不包括.和..的
    //準備好新檔案的FCB的內容,檔案屬性為資料檔案,長度0.
    //分配FAT的空閒塊,-3表示被檔案使用,-1表示檔案結尾
    disk->FAT1[FATFreeItems]=disk->FAT2[FATFreeItems]=-1;
    //將改塊分配到 當前目錄的空閒專案下
    strcpy(dir->fcb[DirFreeItems].filename,filename);
    dir->fcb[DirFreeItems].free=1;//被使用
    dir->fcb[DirFreeItems].attribute=0;//是檔案
    dir->fcb[DirFreeItems].first=FATFreeItems;//分配FAT空閒塊
    dir->fcb[DirFreeItems].length=0;
    dir->fcb[DirFreeItems].data=0;//時間之後弄
    dir->fcb[DirFreeItems].time=0;//時間之後弄
    //檔案新建完畢
    //填寫檔案開啟表項
    openfilelist[OpenFileaddr].fcb=dir->fcb[DirFreeItems];
    char buffer[80];
    memset(buffer,0,sizeof(buffer));
    strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename);
    strcpy(openfilelist[OpenFileaddr].dir,buffer);
    strcpy(openfilelist[OpenFileaddr].fatherfilename,ptrcuridr->fcb.filename);
    openfilelist[OpenFileaddr].pos=OpenFileaddr;
    openfilelist[OpenFileaddr].count=0;
    openfilelist[OpenFileaddr].fcbstate=0;
    openfilelist[OpenFileaddr].topenfile=1;
    //關閉檔案走人
    if(fd!=-1)
        close(fd);
    ptrcuridr=tempp;
    //返回檔案描述符fd,此時的fd跟下標相同,一般不同.
    printf("File Creat Success,The fd is %d\n",OpenFileaddr);
    return OpenFileaddr;
}

rm.cpp

定義

  • 記得遍歷連結串列釋放檔案的空間
    • 連結串列的結尾是-1

程式碼

#include "OS.h"
int close(int fd);
int open_path(char *dirname);
int FileSubstr(char *str);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符
/*--------------------------刪除檔案函式---------------------*/
int rm(char *filename){
/*--------------------------開啟上級目錄---------------------*/
    char newdir[20];
    char dirpath[60];
    USEROPEN *tempp = ptrcuridr;//暫時保管一下ptrcuridr原始值,可能要回溯
    int k=FileSubstr(filename),fd=-1;
    if(k!=-1) {
        filename[k] = 0;
        memset(newdir, 0, sizeof(newdir));
        memset(dirpath, 0, sizeof(dirpath));
        strcpy(newdir, filename + k + 1);
        strcpy(dirpath, filename);
        fd = open_path(dirpath);
        if(fd!=-1) {
            ptrcuridr = openfilelist + fd;
            filename = newdir;
        }
        else {
            printf("error\n");
            return -1;
        }
    }
    //呼叫read,判斷目錄下檔案是否存在
    int BlockDirNum = (ptrcuridr->fcb).first;
    DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8];
    int temp = -1;
    for (int i = 0; i < FCBCOUNT; i++) {
        if (dir->fcb[i].free == 1 && dir->fcb[i].attribute == 0 &&
            strcmp(dir->fcb[i].filename, filename) == 0)//表項被使用,且是檔案,且檔名相等
        {
            temp = i;//檔案存在
            break;
        }
    }
    //要刪除的目錄不存在
    if(temp == -1) {
        printf("rm: failed to remove '%s': No such file or directory\n",filename);
        if(fd!=-1)
            close(fd);
        ptrcuridr=tempp;
        return 0;
    }
    //檢查該檔案是否開啟,若開啟則關閉
    char buffer[80];
    memset(buffer,0,sizeof(buffer));
    strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename);
    for(int i=1;i<MAXOPENFILE;i++) {
        //"."一定是被打開了
        if ((openfilelist[i].topenfile == 1 && strcmp(openfilelist[i].fcb.filename, filename) == 0 &&
             strcmp(openfilelist[i].dir,buffer) ==0 ))
        {
            printf(" The file  been opened,Now Close it !\n");
            close(i);
            break;
        }
    }
    //回收磁碟,一個連結串列
    int TEMP=0;
    for(int p=dir->fcb[temp].first;p!=-1;p=TEMP)
    {
        TEMP=disk->FAT1[p];
        disk->FAT1[p]=disk->FAT2[p]=0;
    }
    //清空該目錄項,free欄位為0,
    memset(&(dir->fcb[temp]),0,sizeof(dir->fcb[temp]));
    //修改長度,表項的fcbstate置為1
    ptrcuridr->fcbstate=1;
    ptrcuridr->fcb.length--;//不包括.和..的
    /*-----------------恢復現場-------------*/
    if(fd!=-1)
        close(fd);
    ptrcuridr=tempp;
    return 1;
}

dowrite.cpp

分析

  • 每次循處理一塊磁碟
  • 檔案指標轉換為邏輯塊塊號blockno 和 塊內偏移blockoff;

程式碼

#include "OS.h"
int open_path(char* dirname);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符

/*---------------實際寫檔案函式----------------*/
int dowrite(int fd,char *text,int len, char wstyle) {
    //申請1024位元組的緩衝區buf
    char *buf = (char *) malloc(1024);
    if (buf == NULL) {
        printf("MALLOC ERROR b\n");
        return -1;
    }
    int tmplen = 0;
    int textpos = 0;
    int textlen = strlen(text);
    //將檔案指標轉換為邏輯塊塊號blockno 和 塊內偏移blockoff;

    /*--------------------分配-----------------*/
    while(tmplen<len) {
        int blockno = (openfilelist[fd].count) / 1024;
        int blockoff = (openfilelist[fd].count) % 1024;
        //尋找磁碟塊blockno
        int currentblock = 0;
        int cnt = 0;
        for (int p = openfilelist[fd].fcb.first; p != -1; p = disk->FAT1[p]) {
            cnt++;
            currentblock = p;
            if (cnt == blockno + 1)
                break;
        }
        int pre = currentblock;
        if (cnt != blockno + 1)//如果找不到這樣的一塊,那麼還需要給它分配blockno+1-cnt塊
        {
            //從currentblock開始分配
            for (int i = 1; i <= blockno + 1 - cnt; i++) {
                //檢查FAT中是否有空閒的盤塊
                int FATFreeItems = -1;
                for (int i = 0; i < BLOCKCOUNT; i++) {
                    if (disk->FAT1[i] == 0) {//沒被使用的塊標記為0
                        FATFreeItems = i;//找到了一個空閒塊
                        break;
                    }
                }
                //如果FAT沒有空閒塊,報錯退出
                if (FATFreeItems == -1) {
                    printf("FAT IS FULL\n");
                    return -1;
                }
                disk->FAT1[pre] = FATFreeItems;
                pre = FATFreeItems;
            }
        }
        //如果是覆蓋寫,或者塊內偏移off不等於0,則將blkno的虛擬磁碟塊全部寫入buff中,否則memset
        if (wstyle == 2 || blockoff != 0) {
            memcpy(buf, disk->Data[currentblock - 8], 1024);
        }
        //將text中的內容暫存到緩衝區buff的第off位元組開始的位置,直到緩衝區滿
        for (int i = blockoff; i < 1024 && textpos < textlen && tmplen<len; i++) {
            buf[i] = text[textpos];
            textpos++;
            tmplen++;  //讀入長度
        }
        memcpy(disk->Data[currentblock - 8], buf, 1024);
        openfilelist[fd].count += tmplen;
    }
    free(buf);
    return tmplen;
}

filewrite.cpp

分析

  • 實際的寫函式

程式碼

#include "OS.h"
int open_path(char* dirname);
int dowrite(int fd,char *text,int len, char wstyle);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符

/*---------------寫檔案函式----------------*/

int filewrite(int fd) {
    int way = 0;
    //檢查fd的有效性
    if (fd >= MAXOPENFILE || fd <= 0) {
        printf("filewirt  ERROR:Is not a legitimate fd \n");
        return -1;
    }else if(openfilelist[fd].topenfile==0){
        printf("filewrite ERROR:該檔案沒有被開啟\n");
        return -1;
    }
    while (1) {
        //提示等待使用者輸入寫方式
        printf(" ------Please enter the way to write---------\n ");
        //1 : 截斷寫 2: 覆蓋寫 3: 追加寫
        printf(" ------1:TRUNC 2:OVER 3:APPEND---------\n ");
        scanf("%d", &way);
        if (1 <= way && way <= 3) break;
        else printf("Input Error,Please Try Again\n");
    }
    // 如果是截斷寫,釋放檔案除第一塊外的磁碟空間內容
    //記憶體使用者開啟表中檔案長度為0,,讀寫指標置為0
    if (way == 1) {
        //釋放檔案除第一塊外的磁碟空間內容
        int TEMP = 0;
        int ok = 1;
        for (int p = openfilelist[fd].fcb.first; p != -1; p = TEMP) {
            TEMP = disk->FAT1[p];
            if (ok != 1) {
                disk->FAT1[p] = disk->FAT2[p] = 0;
            }
            else {
                ok = 0;
            }
        }
        //長度置為0
        openfilelist[fd].fcb.length = 0;
        //讀寫指標置為0
        openfilelist[fd].count = 0;
    }
        //如果是追加寫,修改檔案的當前讀寫指標到檔案的末尾
    else if (way == 3) {
        openfilelist[fd].count = openfilelist[fd].fcb.length;
    }
    //提示使用者,輸入內容通過CTRL+Z結束,使用者可分多次輸入寫入內容,每次用回車結束
    printf(" Input CTRL+D end the input\n ");
    int temp=0;
    char buffer[3000];
    while(gets(buffer)!=0){
        int len=strlen(buffer);
        buffer[len]='\n';
        buffer[len+1]='\0';
        int ret=dowrite(fd,buffer,strlen(buffer),way);
        if(ret==-1) {
            return -1;
        }
        else temp+=ret;
    }
    //如果當前讀寫指標位置大於長度,則更新長度,並置fcbstate置1
    if(openfilelist[fd].count>openfilelist[fd].fcb.length) {
        openfilelist[fd].fcb.length = openfilelist[fd].count;
        openfilelist[fd].fcbstate=1;
    }
    //返回實際寫入的位元組
    return temp;
}

doread.cpp

分析

  • 每次讀一片磁碟

程式碼

#include "OS.h"
int open_path(char* dirname);
int dowrite(int fd,char *text,int len, char wstyle);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符
/*------------------實際讀檔案函式--------------------------*/
//text的指向那個讀出資料的使用者地址
int doread(int fd,int len,char *text){
    //申請1024位元組的緩衝區buf
    char *buf = (char *) malloc(1024);
    if (buf == NULL) {
        printf("MALLOC ERROR b\n");
        return -1;
    }
    int tmplen = 0;
    int textpos = 0;
    //將最終指標轉換為邏輯塊塊號blockno 和 塊內偏移blockoff;
    while(tmplen<len) {
        int blockno = (openfilelist[fd].count) / 1024;
        int blockoff = (openfilelist[fd].count) % 1024;
        //尋找磁碟塊blockno
        int currentblock = 0;
        int cnt = 0;
        for (int p = openfilelist[fd].fcb.first; p != -1; p = disk->FAT1[p]) {
            cnt++;
            currentblock = p;
            if (cnt == blockno + 1)
                break;
        }

          memcpy(buf, disk->Data[currentblock - 8], 1024);

        //
        for (int i = blockoff; i < 1024 && tmplen<len && openfilelist[i].count<openfilelist[i].fcb.length; i++) {
            text[textpos] = buf[i];
            textpos++;
            tmplen++;  //讀入長度
            openfilelist[fd].count;
        }
        memcpy(disk->Data[currentblock - 8], buf, 1024);
    }
        free(buf);
        return tmplen;
}

fileread.cpp

分析

  • 實際的讀函式

程式碼

#include "OS.h"
int open_path(char* dirname);
int dowrite(int fd,char *text,int len, char wstyle);
int doread(int fd,int len,char *text);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符

/*---------------讀檔案函式----------------*/
const  int MAXSIZE=1024*50;
int fileread(int fd,int len){
    char text[MAXSIZE];
    memset(text,0,sizeof(text));
    //檢查fd的有效性
    if (fd >= MAXOPENFILE || fd <= 0) {
        printf("filewirt:Is not a legitimate fd \n");
        return -1;
    }else if(openfilelist[fd].topenfile==0){
        printf("filewrite ERROR:The File Don't Open\n");
        return -1;
    }
    //呼叫do_read()讀取指定檔案的len位元組內容到text[]中.
    int rt=doread(fd,len,text);
    //如果do_read()返回值為負,則顯示出錯資訊,否則將text[]中的內容顯示到螢幕上;
    if(rt==-1){
        printf("READ FAIL");
        return -1;
    }else{
        //輸出text的內容
         for(int i=0;i<len;i++){
             printf("%c",text[i]);
         }
          printf("\n");
    }
}

exitsys.cpp

分析

  • 儲存並退出
  • 關閉所有開啟的檔案

程式碼

#include "OS.h"
int open_path(char* dirname);
int close(int fd);
/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[16];//檔名標示符

/*--------------退出檔案系統函式------------------*/
void exitsys(){
    FILE * fd=fopen("myfsys","w");
    //關閉所有開啟的檔案
    for(int i=0;i<MAXOPENFILE;i++){
        if(openfilelist[i].topenfile==1)
            close(i);
    }
    fwrite(myvhard,sizeof(char),DISKSIZE,fd);
    fclose(fd);
    free(myvhard);
    exit(0);
}

幾個無關緊要的函式

#include "stdio.h"
void help()
{
    printf("\n");
    printf("-----------------------help------------\n");
    printf("format         :-------Format The Disk.\n");
    printf("exit           :-------Exit OS File System AND **NOT SAVE**\n");
    printf("exitsys        :-------Exit OS File System AND SAVE")
    printf("cd     dirname :-------Change Directory\n");
    printf("mkdir  dirname :-------Make Directory.\n");
    printf("rmdir  dirname :-------Delete Directory.\n");
    printf("ls     dirname :-------List Directory .\n");
    printf("creat  filename:-------Creat File\n");
    printf("write  fd      :-------Wirte File\n");
    printf("read   fd      :-------Read File\n");
    printf("rm     filename:-------Remove File\n");
    printf("open   filename:-------Open File\n");
    printf("close  fd      :-------Close File\n");
    printf("open_path\n");
    printf("--------------------------------------\n\n");
}

和自己實現的分割字串

//
// 切割字串,例如/A/B/C/D 切割成 /A/B/C 和 D
//
#include "OS.h"

/*--------------全域性變數-------------------------*/
extern char* myvhard;//虛擬磁碟起始地址
extern string currentdir;//當前目錄
extern string cmd; //讀取指令
extern USEROPEN openfilelist[MAXOPENFILE];//檔案開啟表
extern USEROPEN *ptrcuridr;//當前目錄在檔案開啟表的位置
extern DISK* disk;//將內容結構化
extern char command[50];//檔名標示符
/*-----------------------------------------------*/

int FileSubstr(char *str){
    int len=strlen(str);
    int cnt=0,flag=0;
    for(int i=1;i<len-1;i++)
    {
        if(str[i]=='/')
        {
            cnt++;
            flag=i;
        }
    }
    if(cnt==0) return -1;
    else return flag;
}