File-OS(简单文件系统的实现)
来源:互联网 发布:仙剑传奇网站源码 编辑:程序博客网 时间:2024/05/29 19:03
前言
期末的OS的大作业,写了一个简单的文件管理系统,写了5天左右(实际整个项目历经一个月(大部分时间在挂机),花了不少时间来构思,设计系统的架构。。。。),写的比较辛苦,既然花了这么久的时间,那就拿出来分享下,希望各位指点指正。。
项目github地址
https://github.com/qq1367212627/File-OS
简单的介绍
基本的功能是在磁盘上(D:/VitualDisk/)开辟一个虚拟磁盘,实现对文件的基本操作,下面是具体的系统介绍。
设计原理&目标
File-OS (系统目标)
File Operating System #简单文件系统的实现 1).目的 通过具体的文件存储空间的管理及文件的物理结构、目录结构和文件操作的实现, 加深对文件系统内部功能和实现过程的理解。
2).内容 (1)在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简单的单用户文件系统。 在退出这个简单的文件系统时,应将该虚拟文件系统保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中。
(2)文件存储空间的分配可采用显示链接分配或者其他的办法。
(3)空闲空间的管理可选择位示图或其他的办法。如果采用位示图来管理文件存储空间,并采用显式链接分配方式, 那么可以将位示图合并到FAT中。
(4)文件目录结构采用多级目录结构。为了简单起见,可以不使用索引结点,其中的每个目录项应包含文件名、 物理地址、长度等信息,还可以通过目录项实现对文件的读写保护。
(5)要求提供以下有关操作:
●format:对文件存储器进行格式化,即按照文件系统 的结构对虚拟磁盘空间进行布局, 并在其上创建根目录以及用于管理文件存储空间等的数据结构。
mkdir:用于创建子目录 rmdir:用于删除子目录 ls:用于显示目录 cd:用于更改当前目录 create:用于创建文件 ●open:用于打开文件 ●close:用于关闭文件 ●write:用于写文件 ●read:用于读文件 rm:用于删除文件
文件系统的设计思路&原理
设计基本的系统类结构思路
下图是简单文件系统的类的继承关系及:
文件类(File),文件夹类(Folder)继承自文件控制块FCB类。
访问控制类(Access)用来描述文件夹及文件的访问权限,文件类型(FileType)用来描述文件类型,以区分文件和文件夹。
磁盘管理类(DiskMannger)用来实现与用户的交互与逻辑调用。
文件分配表(FAT)用来存储磁盘块分配占用情况。
文件系统的数据结构
文件夹及文件关系使用树的数据结构保存他们之间的层级包含关系。
文件分配表(FAT)用来存储磁盘块分配占用情况。以下是FAT表的设计思路。
使用2个栈维护盘块索引号,分别维护空的盘块和已占用的盘块。
每个文件维护一张索引表,记录文件存储的盘块号
定义类方法声明&相应的数据结构
Access类:用来描述文件及文件夹的访问权限。
FileType类:描述文件类型
FCB类:描述一个文件的基本属性
File类:文件类
Folder类:文件夹类
FAT类:文件分配表(FAT)用来存储磁盘块分配占用情况
DiskMannger:磁盘管理类,用来实现与用户的交互与逻辑调用。
代码
主函数
main.cpp
#include <windows.h> #include "File.h"#include "DiskMannger.h"using namespace std;int main(){ DiskMannger(); return 0;}
文件控制块(FCB)
FCB.H
#pragma once#include<string>#include "FileType.h"#include "Access.h"#include "FAT.h"#include <time.h>const int N = 4096;using namespace std;class FCB {public: string name;//文件名: 文件名.扩展名 int nodeId;//文件标识:操作系统管理文件的唯一标识。 FileType type;//文件类型:由扩展名给出。 string path;//文件位置:文件所存放设备的具体位置。 int size;//文件大小:以字节或块为单位的文件长度。 Access access;//文件的保护方式:通常有读、写、执行等。 string modifyDate;// 文件的创建或修改日期。 FCB *index[N];//索引表 FCB *father;//父节点 FCB(); ~FCB(); string getTime();//获取系统时间};
FCB.CPP
#pragma once#include "FCB.H"FCB::FCB() { this->access = Write; this->modifyDate = getTime(); this->size = N;}FCB::~FCB(){}string FCB::getTime(){ time_t t = time(0); char tmp[64]; strftime(tmp, sizeof(tmp), "%Y/%m/%d %X", localtime(&t)); return tmp;}
文件分配表(FAT类)
FAT.H
#pragma once#include<stack>#include<algorithm>const static int BLOCK_SIZE = 4096/sizeof(bool);using namespace std;class FAT {public: stack<int>freeDiskBlock;//空磁盘块栈 stack<int>fullDiskBlock;//占用磁盘块 void init(string blocks[]); int getBlock(); void addBlock(int block, string blocks[]);//获取一个空的磁盘块};Contact GitHub API Training Shop Blog About
FAT.CPP
#include<cstring>#include "FAT.h"void FAT::init(string blocks[])//初始化磁盘{ for (int i = 0; i < BLOCK_SIZE; i++) { this->freeDiskBlock.push(i); blocks[i].clear(); }}int FAT::getBlock()//获取空磁盘{ if (this->freeDiskBlock.size() > 0) { int blockId = this->freeDiskBlock.top(); this->freeDiskBlock.pop(); this->fullDiskBlock.push(blockId); return blockId; } return -1;}void FAT::addBlock(int block, string blocks[])//回收磁盘块{ this->freeDiskBlock.push(block); blocks[block].clear();}
文件类
File.h
#pragma once#include "FCB.H"#include<string>class File:public FCB{public: //构造函数 File(); File(string _name, FileType _type, FAT & fat); //析构函数 ~File(); //序列化 void Serialization(); //反序列化 void Deserialization(); bool addContent(const char * content, string blocks[], FAT & fat); //文件索引 int index[N]; //上一级文件夹 FCB* father; void release(FAT & fat, string* blocks); string toString(string blocks[]); //释放磁盘块};
File.cpp
#include "File.h"File::File() {}File::File(string _name, FileType _type,FAT &fat){ this->name = _name; this->type = _type; this->size = 0; this->index[size] = fat.getBlock();//ΪÎļþ·ÖÅä¿Õ¼ä}File::~File(){}void File::Serialization(){}void File::Deserialization(){}bool File::addContent(const char * content,string blocks[],FAT &fat){ int len = strlen(content); for (int i = 0; i < len; i++) { if (blocks[index[size]].length()<=N) { blocks[index[size]] += content[i]; } else { index[++size] = fat.getBlock(); blocks[index[size]] += content[i]; } } this->modifyDate = this->getTime(); return false;}void File::release(FAT & fat, string * blocks){ for (int i = 0;i<this->size;i++) { fat.addBlock(index[i],blocks); }}string File::toString(string blocks[]){ string s; for (int i = 0; i <= this->size; i++) { s += blocks[index[i]]; } return s;}
文件夹类
Folder.h
#pragma once#include "FCB.h"#include "File.h"#include<vector>#include<string>class Folder:public FCB{public: vector<FCB * >child; void addChild(FCB* file); Folder(string _name, FileType _type); bool count(FCB *file); FCB* find(FCB *file); bool erase(FCB* file); int size();private: int childSize;};
Folder.cpp
#pragma once#include "Folder.h"void Folder::addChild(FCB * file){ this->child.push_back(file);}Folder::Folder(string _name, FileType _type){ this->name = _name; this->type = _type;}bool Folder::count(FCB * file){ int size = child.size(); for (int i = 0; i < size; i++) { if (child[i]->type == file->type&&child[i]->name == file->name) { return true; } } return false;}FCB* Folder::find(FCB * file){ int size = child.size(); for (int i = 0; i < size; i++) { if (child[i]->type == file->type&&child[i]->name == file->name) { return child[i]; } } return NULL;}bool Folder::erase(FCB * file){ int size = child.size(); vector<FCB*>::iterator it; for (it = child.begin();it!=child.end();it++) { if ((*it)->type == file->type&&(*it)->name == file->name) { child.erase(it); return true; } } return false;}int Folder::size(){ return child.size();}
磁盘管理器类
DiskMannger.h
#pragma once#include "Folder.h"class DiskMannger{public: void DiskWrite(File * file); bool DiskMkdir(string dirName);//创建磁盘文件夹 bool DiskRmdir(string dirName);//删除磁盘文件夹 bool DiskCkdir(string dirName); void DiskRmdir(Folder * f); //检查磁盘是否存在文件夹 DiskMannger();//磁盘构造函数 ~DiskMannger(); //磁盘类析构函数 void format(string * blocks);//: 对文件存储器进行格式化。 void Mkdir(); void Rmdir(); void ls(); //: 用于显示目录 void cd(); //: 用于更改当前目录 void create();//: 用于创建文件 void open(); //: 用于打开文件 void close(); //: 用于关闭文件 void write(const char * s, File * file);//: 用于写文件 void read(const char * s);//: 用于读文件 void rm(); //: 用于删除文件private: Folder *root;};
DiskMannger.cpp
#include <windows.h> #include<stack>#include<iostream>#include<iomanip>#include<queue>#include <fstream> #include<direct.h> #include<io.h> #include "DiskMannger.h"#include "Folder.h"#include "FileType.h"#include "Access.h"#include "FAT.h"const string ACCESS[] = { "只读","可修改","可执行" };const string rootPath = "D:/VitualDisk/";queue<FCB*> persistQueue;//持久化队列FAT fat;string blocks[N];ofstream *out = NULL;ifstream *in = NULL;using namespace std;void DiskMannger::DiskWrite(File * file){ //文件输出流 printf("%s\n", file->path.c_str()); //freopen(file->name.c_str(), "w", stdout); out = new ofstream(file->path.c_str()); if (out->is_open()) { out->close(); } //cout << "hello world" << endl; // fclose(stdout);//关闭文件}bool DiskMannger::DiskMkdir(string dirName){ printf("%s\n",dirName.c_str()); return _mkdir(dirName.c_str()) == 0;}bool DiskMannger::DiskRmdir(string dirName){ return rmdir(dirName.c_str()) == 0;}bool DiskMannger::DiskCkdir(string dirName){ if (_access(dirName.c_str(), 0) == -1) { return _mkdir(dirName.c_str()) == 0; } return false;}void DiskMannger::DiskRmdir(Folder *f){ //DFS删除 for (int i = 0; i < f->child.size(); i++) { if (f->child[i]->type == DOCUMENT) { printf("%s\n", f->child[i]->path.c_str()); remove(f->child[i]->path.c_str()); }else { this->DiskRmdir((Folder*)f->child[i]); } } printf("%s\n", f->path.c_str()); this->DiskRmdir(f->path.c_str());}DiskMannger::DiskMannger(){ fat.init(blocks); root = new Folder(rootPath,FileType::FOLDER); root->path = rootPath; this->DiskMkdir(rootPath); //设置磁盘根为目录 //设置根节点的父节点为自身 root->father = root; cout << "欢迎!!-----------您可输入help获得帮助------------" << endl<< "\n[root@localhost "+rootPath+"]# "; string opear,cmd; while (cin >> cmd) { if (cmd == "format") { this->format(blocks); } else if (cmd == "mkdir") { this->Mkdir(); } else if (cmd == "rmdir") { this->Rmdir(); } else if (cmd == "ls") { this->ls(); } else if (cmd == "cd") { this->cd(); } else if (cmd == "create") { this->create(); } else if (cmd == "open") { this->open(); } else if (cmd == "close") { this->close(); } else if (cmd == "rm") { this->rm(); } else if (cmd == "exit") { printf("%s\n", "再见!"); break; } else if(cmd=="help"){ cout << "\n●format:对文件存储器进行格式化.\n"<< "●mkdir:用于创建子目录\n" << "●rmdir : 用于删除子目录\n" << "●ls : 用于显示目录\n" << "●cd : 用于更改当前目录\n" << "●create : 用于创建文件\n" << "●open : 用于打开文件\n" << "●close : 用于关闭文件\n" << "●write : 用于写文件\n" << "●read : 用于读文件\n" << "●rm : 用于删除文件\n" << "●exit : 退出系统\n" <<endl; } else { cout << "输入指令错误,请重新输入!!" << endl; } cout << "\n[root@localhost "+this->root->path+" ]# "; }}DiskMannger::~DiskMannger(){}void DiskMannger::format(string *blocks){ fat.init(blocks); //回退到根目录 while (root->father != root) { this->root = (Folder*)(this->root->father); } this->DiskRmdir(this->root); root->child.clear(); printf("%s\n", "磁盘格式化成功!");}void DiskMannger::Mkdir(){ string name; cin >> name; Folder *childFile = new Folder(name,FileType::FOLDER); //设置父节点 childFile->father = (this->root); childFile->path = this->root->path + name + "/" ; //判断是否文件重复 if (this->root->count(childFile)) { //文件重复报错 cout << "创建文件夹失败,文件夹名出现重复" << endl; }else { cout << "创建文件夹成功" << endl; this->DiskMkdir(childFile->path); this->root->addChild(childFile); }}void DiskMannger::Rmdir(){ string name; cin >> name; Folder *childFile =new Folder(name, FOLDER); childFile = (Folder*) this->root->find(childFile); if (this->root->erase(childFile)) { //文件重复报错 this->DiskRmdir(childFile); cout << "删除文件夹成功" << endl; }else { cout << "无此文件夹 ,删除文件夹失败" << endl; }}void DiskMannger::ls(){ cout << setw(10) << "访问权限" << setw(20) <<"文件大小" << setw(25) << "修改日期" << setw(20) << "文件名" << endl; int size = this->root->size(); for(int i= 0;i<size;i++) { cout << setw(10) << ACCESS[this->root->child[i]->access] << setw(20) << (this->root->child[i]->type != FOLDER ? ((File*)this->root->child[i])->toString(blocks).size() : 4096) << setw(25)<<this->root->child[i]->modifyDate << setw(20)<<this->root->child[i]->name <<endl; }}void DiskMannger::cd(){ string name; cin >> name; if (name == "..") { this->root = (Folder*)(this->root->father); } else { if (this->root->count(new Folder(name, FOLDER))) { if (this->root->find(new Folder(name, FOLDER))->type != FOLDER) { cout << "无此文件夹" << endl; } else { root = (Folder*)this->root->find(new Folder(name, FOLDER)); } } else { cout << "无此文件夹 " << endl; } }}void DiskMannger::create(){ string name; cin >> name; File *childFile = new File( name, DOCUMENT,fat); //设置父节点 childFile->father = (this->root); childFile->path = this->root->path + name; //判断是否文件重复 if (this->root->count(childFile)) { //文件重复报错 cout << "创建文件失败,文件名出现重复!!" << endl; } else { cout << "创建文件成功!" << endl; this->root->addChild(childFile); this->DiskWrite(childFile); }}void DiskMannger::open(){ string name,cmd; cin >> name; File * file = (File*)this->root->find(new File(name, DOCUMENT,fat)); if (file!=NULL) { printf("%s\n", "文件读写流打开成功!"); cout << "\n[root@localhost " + this->root->path + " ]# "; while (cin>>cmd) { cout << "\n[root@localhost " + this->root->path + " ]# "; if (cmd == "write") { this->write(file->path.c_str(), file); } else if (cmd == "read") { this->read(file->path.c_str()); } else if (cmd == "close") { this->close(); break; } } } else { printf("%s\n", "无法打开文件读写流,无此文件!"); }}void DiskMannger::close(){ if (out == NULL||in==NULL) { printf("%s\n", "无文件读写流需要关闭!"); }else { out->close(); in->close(); printf("%s\n", "文件读写流关闭成功!"); }}void DiskMannger::write(const char *s, File* file){ string content; cin >> content; if (in != NULL)in->close(); file->addContent(content.c_str(), blocks, fat);//添加内容到文件中 content = file->toString(blocks); out = new ofstream(s); if (out->is_open()) { *out << content; } out->close();}void DiskMannger::read(const char *s){ char *content = new char[N]; if (out != NULL)out->close(); in = new ifstream(s); if (in->is_open()) { *in >> content; } in->close(); cout << content;}void DiskMannger::rm(){ string name; cin >> name; File *childFile = new File(name, DOCUMENT,fat); if (this->root->count(childFile)) { //文件重复报错 childFile =(File*) this->root->find(childFile); remove(childFile->path.c_str()); childFile->release(fat,blocks); this->root->erase(childFile); cout << "删除文件成功!" << endl; } else { cout << "无此文件 ,删除文件失败" << endl; }}
访问控制类(Access)
Access.h
#pragma onceenum Access { ReadOnly,//只读 Write, //写 Executable//可执行};
文件类型(FileType)
FileType.h
#pragma onceenum FileType { FOLDER , //文件夹 DOCUMENT//文件};
以下为主要功能的函数设计思路
DiskMannger();//磁盘构造函数
初始化磁盘类,逻辑调用与用户交互通过此函数实现。设置磁盘的根目录为自身,即设置一个树的root节点
void format(); //: 对文件存储器进行格式化。
格式化磁盘,包括对fat表的初始化,磁盘文件的删除,删除现存的节点关系,结构初始化。
void Mkdir();
判断是否存在同名文件夹,若不存在则添加一个文件夹的节点到这个树的目录结构上,在磁盘对应的文件夹创建一个新的文件夹
void Rmdir();
判断是否存在存在在这个目录中,然后从这个树的目录结构上删除这个文件夹的节点,在磁盘对应的文件夹删除文件夹,
void ls(); //: 用于显示目录
遍历当前的文件夹下的文件及文件夹,通过判断文件还是文件夹来控制显示的颜色,文件夹显示为黄色,而文件显示为白色。
void cd(); //: 用于更改当前目录
先判断是否是 .. 这个目录,若为 .. ,则将当前的指针指向当前节点的父节点,否则在当前的目录先查询是否有这个文件夹,若存在则切换,将指针指向目标地址,否则就输出提示错误信息。
void create();//: 用于创建文件
首先在判断当前的文件夹是否存在有相同的文件名,若已经存在则输出错误提示信息,否则创建一个File节点对象添加到当前的文件夹下,作为当前文件夹的子节点,然后创建一个文件到磁盘上。
void open(); //: 用于打开文件
先判断文件是否存在,若存在则创建ofstream,ifstream对象,打开目标的文件读写数据流,开始准备读写数据。若不存在则输出错误提示。
void close(); //: 用于关闭文件流
判断当前是否有文件流需要关闭,若存在输入输出流,则将其调用close函数关闭,否则输出错误提示信息
void write(const char * s, File * file);//: 用于写文件
用户输入字符,将字符追加到文件中,由ifstream文件流存储到磁盘,将字符追加到文件对象中,由文件对象添加到磁盘块中。
void read(const char * s);//: 用于读文件
读取ofstream流中的文件并输出。
void rm(); //: 用于删除文件
在当前目录查找是否存在文件,若存在则:使用
结尾
以上就是整个系统的设计啦,写的不好希望多多指出来,我会尽快修改,就这样啦~(≧▽≦)/~
- File-OS(简单文件系统的实现)
- [OS][FileSystem]文件系统的实现
- 简单文件系统的实现
- 简单文件系统的实现
- 简单文件系统的实现
- 简单文件系统的实现
- 简单文件系统的实现
- 简单文件系统的实现
- linux下的简单文件系统(file system)
- 一个简单文件系统的实现
- 一个简单文件系统的实现
- 操作系统课程设计--简单文件系统的实现
- 简单虚拟文件系统的设计与实现
- 使用ICE实现一个简单的文件系统
- 实现一个简单的aufs文件系统
- 简单文件系统的实现(beta1.1)
- 一步一步实现一个简单的OS(HelloWorld)
- Ruby File类实现操作文件系统的方法
- android mvp模式讲解
- Thymeleaf【第一篇】 结合springmvc
- Spring4学习笔记(三):依赖注入的方式与细节
- 详解最大似然估计(MLE)、最大后验概率估计(MAP),以及贝叶斯公式的理解
- [Web]Jquery圆点的图片轮播
- File-OS(简单文件系统的实现)
- [leetcode]: 9. Palindrome Number
- i miss you
- sublime text3中中文件名显示为方框,如何解决?
- Kotlin Reference (二) idioms 一些常用方式
- 如何节省内存空间
- 蓝桥-BASIC-27-2n皇后问题
- react路由提高(Prompt、Redirect、match、Switch)
- xml生成