File-OS(简单文件系统的实现)
2017-05-31 01:03
609 查看
前言
期末的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 ;//索引表 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 ; //上一级文件夹 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 ; 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 ; 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 once enum Access { ReadOnly,//只读 Write, //写 Executable//可执行 };
文件类型(FileType)
FileType.h
#pragma once enum 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(); //: 用于删除文件
在当前目录查找是否存在文件,若存在则:使用
结尾
以上就是整个系统的设计啦,写的不好希望多多指出来,我会尽快修改,就这样啦~(≧▽≦)/~相关文章推荐
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
- 一个简单文件系统的实现
- [OS][FileSystem]文件系统的实现
- asp.net,C#,html控件的File控件实现多文件上传简单实例,vs2010
- 实现简单文件系统文件相关操作
- [OS][FileSystem]文件系统的实现
- ICE笔记(06):简单文件系统的设计、实现
- C下学生管理系统:从文件中读取30位学生的信息(含邮箱),并实现简单的增、删、查找、统计(邮箱使用人数)。---附程序哦!
- 模拟实现简单文件系统并实现数据库完整性检查
- Drupal Private File System 私有文件系统实现
- 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子
- 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子
- 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子
- 一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子
- 一个简单文件系统的实现
- Linux下简单配置SAMBA服务,实现与Windows系统文件共享.
- 简单文件系统的实现
- ICE笔记(06):简单文件系统的设计、实现
- UrlDownloadtoFile文件下载,进度条,下载暂停,停止的简单实现
- linux系统编程之文件与I/O(五):文件的内核结构file和dup实现重定向