简单文件系统的实现
要求
内存中开辟一块
虚拟磁盘空间
作为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统
中的文件系统。在退出该文件系统的使用时,虚拟文件系统以一个文件的方式保存到磁盘中,以便下次可以把它恢复到内存的虚拟存储空间
实际实现
- 以上两点均实现
能处理绝对路径和相对路径的命令
- 例如 :
cd /home/zy/Desktop/
这样的绝对路径cd ../hah/1/2
这样的相对路径
mkdir
,rmdir
,cd
,creat
,rm
均支持open_path
是open
的升级版,也是支持上述函数实现的主要函数。
- 例如 :
包装
open
,read
,close
实现了一个cat
直接打印文件内容。- 检查文件是否打开,如果打开了直接进行下一步,没有就打开
read
出所有内容- 如果之前不是打开的那么就关闭文件。
截图
建立目录树,
/home
是用户的根目录/home
下有/zy
/zy
下有/Documents
,/Desktop
,/Viedeos
,Music
等在
/home/zy/Documents
目录下建立一个文件Hello.txt
- 并输入内容
Hello World!Fisrt
,能正确显示长度和文件内容。 - 测试了
creat
,open
,close
,read
,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");