實(shí)驗(yàn) 簡(jiǎn)單文件系統(tǒng)的實(shí)現(xiàn)

1往踢、實(shí)驗(yàn)?zāi)康?/h1>

通過具體的文件存儲(chǔ)空間的管理、文件的物理結(jié)構(gòu)徘层、目錄結(jié)構(gòu)和文件操作的實(shí)現(xiàn)峻呕,加深對(duì)文件系統(tǒng)內(nèi)部功能和實(shí)現(xiàn)過程的理解。

2趣效、實(shí)驗(yàn)內(nèi)容

  1. 在內(nèi)存中開辟一個(gè)虛擬磁盤空間作為文件存儲(chǔ)器瘦癌,在上面實(shí)現(xiàn)一個(gè)簡(jiǎn)單單用戶文件系統(tǒng)。退出時(shí)應(yīng)該將該虛擬文件系統(tǒng)保存到磁盤上英支,以便下次可以再將它恢復(fù)到內(nèi)存對(duì)虛擬磁盤空間中佩憾。
  2. 文件存儲(chǔ)空間對(duì)分配可以采用顯式鏈接分配或者其他的辦法。
  3. 空閑空間的管理可以選擇位示圖或者其他的辦法干花。如果采用位示圖來管理文件存儲(chǔ)空間妄帘,并采用顯式鏈接分配方式,那么可以將位示圖合并到FAT中池凄。
  4. 文件目錄結(jié)構(gòu)采用多級(jí)目錄結(jié)構(gòu)抡驼。為了簡(jiǎn)單起見,可以不使用索引結(jié)點(diǎn)肿仑,其中的每個(gè)目錄項(xiàng)應(yīng)包含文件名致盟、物理地址、長度等信息尤慰,還可以通過目錄項(xiàng)實(shí)現(xiàn)對(duì)文件對(duì)讀和寫的保護(hù)馏锡。
  5. 要求提供以下有關(guān)的操作:
√format:對(duì)文件存儲(chǔ)器進(jìn)行格式化,即按照文件系統(tǒng)對(duì)結(jié)構(gòu)對(duì)虛擬磁盤空間進(jìn)行布局伟端,并在其上創(chuàng)建根目錄以及用于管理文件存儲(chǔ)空間等的數(shù)據(jù)結(jié)構(gòu)杯道。
√mkdir:用于創(chuàng)建子目錄;
√rmdir:用于刪除目錄责蝠;
√ls:用于顯示目錄党巾;
√cd:用于更改當(dāng)前目錄;
√create:用于創(chuàng)建文件霜医;
√open:用于打開文件齿拂;
√close:用于關(guān)閉文件;
√write:用于寫文件肴敛;
√read:用于讀文件
√rm:用于刪除文件署海。

代碼

#include <iostream>
#include <vector>
#include <iomanip>
#include <fstream>
using std::string;
using std::vector;
using std::cout;
using std::endl;
using std::cin;
using std::ifstream;
using std::ofstream;
using std::ios;
class FCB{
public:
    int first_block;
    string fileName;
    int size;
    int real_size;
    FCB(int first_block0,const string &fileName0, int size0, int real_size0):
        first_block(first_block0),
        fileName(fileName0),
        size(size0),
        real_size(real_size0*4) {
    }
}; //文件控制塊
class DirItem { //文件樹
    string name;
    vector<FCB*> files; //目錄下的文件
    vector<DirItem*> dirs; //目錄下的文件夾,樹節(jié)點(diǎn)
public:
    DirItem(const string& name0):name(name0) {}
    void addFile(int first_block, const string& fileName,int size, int real_size) {
        for (auto i = files.begin(); i != files.end(); i++) {
            if ((*i)->fileName == fileName) {
                cout << "same file name" << endl;
                return;
            }
        }
        files.push_back(new FCB(first_block, fileName, size, real_size));
    }
    void addDir(DirItem* dir) {
        dirs.push_back(dir);
    }
    vector<DirItem*> getDirs() {
        return dirs;
    }
    vector<FCB*> getFiles() {
        return files;
    }
    string getName() {
        return name;
    }
    void del_file(const string& fileName) {
        for (auto i = files.begin(); i != files.end(); i++) {
            if ((*i)->fileName == fileName) {
                files.erase(i);
                break;
            }
        }
    }
    void del_dir(const string& fileName) {
        for (auto i = dirs.begin(); i != dirs.end(); i++) {
            if ((*i)->getName() == fileName) {
                dirs.erase(i);
                break;
            }
        }
    }
    void clear() {
        for (DirItem* item : dirs) {
            delete item;
        }
        for (FCB* item : files) {
            delete item;
        }
        dirs.clear();
        files.clear();
    } //遞歸刪除時(shí)用到,刪除當(dāng)前目錄下的目錄和文件的指針
};

class diskMgr { //磁盤
    vector<int> blocks; //fat表
    int n = 16;
    int block_num = n*n;
    int block_size = 4; //每塊4B
    int disk_capacity = block_num * block_size; //1M
    vector<vector<int>> bit_map; //0空叹侄,1有巩搏,位視圖
public:
    vector<char> disk;
    diskMgr() {
        disk = vector<char>(disk_capacity, '\0');
        blocks = vector<int>(block_num, -1);
        bit_map = vector<vector<int>>(n, vector<int>(n, 0));
    }
    int getSize(int blockNum) {
        int n = 0;
        while (blockNum != -1) {
            n++;
            blockNum = blocks[blockNum];
        }
        return n;
    } //當(dāng)前塊號(hào)開始的文件一個(gè)有多少塊兒
    int find_empty_block() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (bit_map[i][j] == 0) {
                    return n*i+j;
                }
            }
        }
        return -1;
    }//找到一個(gè)空閑盤塊,從位視圖
    void update_bit_map(int x, int notempty) {
        int i = x / n,j = x % n;
        bit_map[i][j] = notempty;
    }//更新位視圖
    void del(int blockNum) {
        while (blockNum != -1) {
            for(int i = 0; i < block_size; i++) {
                disk[blockNum * block_size + i] = '\0';
            }
            update_bit_map(blockNum, 0);
            int t = blocks[blockNum];
            blocks[blockNum] = -1;
            blockNum = t;
        }
    } //刪除文件
    vector<char> read(int blockNum) {
        vector<char> data;
        while (blockNum != -1) {
            for(int i = 0; i < block_size; i++) {
                data.push_back(disk[blockNum * block_size + i]);
            }
            blockNum = blocks[blockNum];
        }
        return data;
    } //讀取文件
    int write(vector<char> data) {
        int first_block = find_empty_block(); //找到初始位置
        if (first_block == -1) return -1;
        int len = int(data.size());
        int blockn = len%block_size == 0 ? len/block_size : len/block_size+1; //一共需要的盤塊兒數(shù)
        int next_block = first_block;
        int temp = next_block;
        int fix = (block_size - len % block_size) % block_size;

        for (int i = 0; i < fix; ++i) { //數(shù)據(jù)長度對(duì)齊
            data.push_back('*');
        }
        for (int i = 0; i < blockn; i++) { //存數(shù)據(jù)
            if (temp == -1) {
                break;
            }
            next_block = temp;
            for (int j = 0; j < block_size; j++) {
                disk[next_block*block_size+j] = data[i*block_size+j];
            }
            update_bit_map(next_block, 1);
            temp = find_empty_block();
            blocks[next_block] = temp;

        }
        blocks[next_block] = -1;
        return first_block;
    }

};
#define chart_head std::left << std::setw(len+1) << std::setfill('-') << ""
#define chart_cell "|" << std::left << std::setw(len) << std::setfill(' ')
class fileMgr {
    DirItem * root; //根節(jié)點(diǎn)
    diskMgr dm;//磁盤管理器
    DirItem * cur; //當(dāng)前命令行執(zhí)的工作目錄
    string cur_path; //工作命令
    DirItem* addmdir(DirItem * node, string name) {
        DirItem* newNode = new DirItem(name);
        node->addDir(newNode);
        return newNode;
    }
public:

    fileMgr() {
        root = new DirItem("/");
        DirItem * temp = addmdir(addmdir(root, "apps"), "tencent");
        addmdir(temp, "qq");
        addmdir(temp, "qqgame");
        addmdir(temp, "qqmusic");
        temp = addmdir(root, "docs");
        addmdir(temp, "words");
        addmdir(temp, "ppts");
        addmdir(temp, "excels");

        root->addDir(new DirItem("pics"));
        root->addDir(new DirItem("musics"));
        cur = root;
        cur_path = "/";
        cout_hint();
    } //初始化一些文件夾
    void ls() {
        int len = 20;
        cout
            << chart_head << chart_head << chart_head << chart_head << endl
            << chart_cell << "file/dir name"
            << chart_cell << "type"
            << chart_cell << "size"
            << chart_cell << "real size" << "|" << std::endl
            << chart_head << chart_head << chart_head << chart_head << endl;
        vector<DirItem*> dirs = cur->getDirs();
        for (auto i = dirs.begin(); i != dirs.end(); i++) {
            cout
                << chart_cell << (*i)->getName()
                << chart_cell << "directory"
                << chart_cell << "--"
                << chart_cell << "--" << "|" << std::endl;
        } 
        vector<FCB*> files = cur->getFiles();
        for (auto i = files.begin(); i != files.end(); i++) {
            cout
                    << chart_cell << (*i)->fileName
                    << chart_cell << "file"
                    << chart_cell << (*i)->size
                    << chart_cell << (*i)->real_size << "|" << std::endl;
        }
        cout
            << chart_head << chart_head << chart_head << chart_head << endl;
        cout_hint();
    }
    void cout_hint() {
        cout << "\n" << cur_path << "> ";
    } //輸出命令行提示符
    void cd(string name) {
        if (name == "..") {
            if(cur_path == "/") {
                cout_hint();
            } else {
                if (*cur_path.rbegin() == '/') {
                    cur_path.pop_back();
                }
                cur_path = cur_path.substr(0, cur_path.rfind('/'));
                if (cur_path.length() == 0) {
                    cur_path = "/";
                }
                cur = find_dir_node(cur_path);
                cout_hint();
                return;
            }
        }
        DirItem* node = cur;
        for(DirItem* item : node->getDirs()){
            if (item->getName() == name) {
                cur = item;
                cur_path += name+"/";
                cout_hint();
                return;
            }
        }
        cout << "no such dir";
        cout_hint();
    }
    void cdn(string path) {
        cur = find_dir_node(path);
        if (*path.rbegin() != '/') {
            path.push_back('/');
        }
        if (*path.begin() != '/') {
            path = "/" + path;
        }
        cur_path = path;
        cout_hint();
    }
    DirItem* find_dir_node(string path) {
        if (path[0] == '/') {
            path = path.substr(1, path.length()-1);
        }
        if (*path.rbegin() != '/') {
            path.push_back('/');
        }
        int r = 0;
        DirItem* node = root;
        if (path == "/") return node;
        while (r != -1) {
            r = path.find('/');
            if (r != -1) {
                string dir = path.substr(0, r);
                bool find = false;
                for(DirItem* item : node->getDirs()){
                    if (item->getName() == dir) {
                        node = item;
                        find = true;
                        break;
                    }
                }
                if (!find) {
                    return nullptr;
                }
                path = path.substr(r+1, path.length() - r - 1);
            } else {
                break;
            }
        }
        return node;
    }
    void create_file(const string& fileName, const vector<char>& data) {
        DirItem *node = cur;
        if (node != nullptr) {
            int fb = dm.write(data);
            if(fb == -1) {
                cout << "no enough disk storage";
                cout_hint();
            }
            int size = dm.getSize(fb);
            node->addFile(fb, fileName, data.size(), size);
        }
        cout_hint();
    }
    void create_file(string path, const string& fileName, const vector<char>& data) {
        DirItem *node = find_dir_node(path);
        if (node != nullptr) {
            int fb = dm.write(data);
            int size = dm.getSize(fb);
            node->addFile(fb, fileName, data.size(), size);
        }
    }
    void create_dir(const string& dirName) {
        if (cur != nullptr) {
            cur->addDir(new DirItem(dirName));
        }
        cout_hint();
    }
    void create_dir(string path, const string& dirName) {
        DirItem * node = find_dir_node(path);
        if (node != nullptr) {
            node->addDir(new DirItem(dirName));
        }
    }
    void del_dir(DirItem* node) {
        if (node != nullptr) {
            for(FCB* fcb : node->getFiles()) {
                dm.del(fcb->first_block);
                node->del_file(fcb->fileName);
            }
            for(auto i : node->getDirs()) {
                del_dir(i);
            }
            node->clear();
        }
    }
    void del_dir(const string& fileName) {
        if (cur != nullptr) {
            for (auto i : cur->getDirs()) {
                if(i->getName() == fileName) {
                    del_dir(i);
                    cur->del_dir(i->getName());
                    cout_hint();
                    return;
                }
            }
        }
        cout << "no such directory";
        cout_hint();
    }
    void del_file(const string& fileName) {
        DirItem*node = cur;
        if (node != nullptr) {
            for(FCB* fcb : node->getFiles()) {
                if (fcb->fileName == fileName) {
                    dm.del(fcb->first_block);
                    node->del_file(fileName);
                    cout_hint();
                    return;
                }
            }
        }
    }
    void del_file(string path, const string& fileName) {
        DirItem*node = find_dir_node(path);
        if (node != nullptr) {
            for(FCB* fcb : node->getFiles()) {
                if (fcb->fileName == fileName) {
                    dm.del(fcb->first_block);
                    node->del_file(fileName);
                    return;
                }
            }
        }
    }
    void show(const vector<char>& v) {
        for (char i : v) {
            cout << i;
        }
    }
    void read(const string& fileName) {
        if (cur != nullptr) {
            for(FCB* fcb : cur->getFiles()) {
                if (fcb->fileName == fileName) {
                    vector<char> data = dm.read(fcb->first_block);
                    show(data);
                    cout_hint();
                    return;
                }
            }
        }
        cout << "file not found";
        cout_hint();
    }
    vector<char> read(string path, const string& fileName) {
        DirItem*node = find_dir_node(path);
        if (node != nullptr) {
            for(FCB* fcb : node->getFiles()) {
                if (fcb->fileName == fileName) {
                    return dm.read(fcb->first_block);
                }
            }
        }
        return {};
    }


};
int main() {


    fileMgr fm;
    /*ifstream Myfile2;
    Myfile2.open("file_sys.disk",ios::binary);
    //二進(jìn)制打開趾代,缺省為文本贯底,ios::out,ios::in,文本輸入輸出用<<,>>
    Myfile2.read((char *)&fm,sizeof(fileMgr));
    Myfile2.close();*/
    string ins, para;
    while(cin >> ins) {
        if(ins == "ls") {
            fm.ls();
        } else if(ins == "cd") {
            cin >> para;
            fm.cd(para);
        } else if (ins == "read") {
            cin >> para;
            fm.read(para);
        }  else if (ins == "mkdir") {
            cin >> para;
            fm.create_dir(para);
        } else if (ins == "rmdir") {
            cin >> para;
            fm.del_dir(para);
        } else if (ins == "mkfile") {
            cin >> para;
            string c = "";
            cout << "contents:\n";
            string data;
            while(c != "#") {
                data += c;
                std::getline(cin, c);
                data += '\n';
            }
            int k = 0;
            while (data[k] == '\n') k++;
            data = data.substr(k, data.length()-k);
            vector<char> vdata;
            for(char i : data) {
                vdata.push_back(i);
            }
            fm.create_file(para, vdata);
        } else if (ins == "rmfile") {
            cin >> para;
            fm.del_file(para);
        } else if (ins == "exit" || ins == "quit") {
            break;
        } else if (ins == "cdn") {
            cin >> para;
            fm.cdn(para);
        } else {
            string c;
            std::getline(cin, c);
            ins += " " + c;
            system(ins.c_str());
            cout << "unknown cmd:" << ins << endl;
            fm.cout_hint();
        }
    }


    /*ofstream file;
    file.open("file_sys.disk",ios::binary);
    //緩存的類型是 unsigned char *,需要類型轉(zhuǎn)換
    file.write((char *)&fm,sizeof(fileMgr));  //winServer為類對(duì)象
    file.close();*/
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撒强,一起剝皮案震驚了整個(gè)濱河市禽捆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌飘哨,老刑警劉巖胚想,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芽隆,居然都是意外死亡浊服,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門胚吁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牙躺,“玉大人,你說我怎么就攤上這事腕扶∧蹩剑” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵半抱,是天一觀的道長脓恕。 經(jīng)常有香客問我,道長窿侈,這世上最難降的妖魔是什么炼幔? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮史简,結(jié)果婚禮上江掩,老公的妹妹穿的比我還像新娘。我一直安慰自己乘瓤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布策泣。 她就那樣靜靜地躺著衙傀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪萨咕。 梳的紋絲不亂的頭發(fā)上统抬,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼聪建。 笑死钙畔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的金麸。 我是一名探鬼主播擎析,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼挥下!你這毒婦竟也來了揍魂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤棚瘟,失蹤者是張志新(化名)和其女友劉穎现斋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偎蘸,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庄蹋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迷雪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片限书。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖振乏,靈堂內(nèi)的尸體忽然破棺而出蔗包,到底是詐尸還是另有隱情,我是刑警寧澤慧邮,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布调限,位于F島的核電站,受9級(jí)特大地震影響误澳,放射性物質(zhì)發(fā)生泄漏耻矮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一忆谓、第九天 我趴在偏房一處隱蔽的房頂上張望裆装。 院中可真熱鬧,春花似錦倡缠、人聲如沸哨免。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琢唾。三九已至,卻和暖如春盾饮,著一層夾襖步出監(jiān)牢的瞬間采桃,已是汗流浹背懒熙。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留普办,地道東北人工扎。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像衔蹲,于是被迫代替她去往敵國和親肢娘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容