当前位置:文档之家› 简单文件系统模拟实验

简单文件系统模拟实验

简单文件系统模拟实验实验目的通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统功能和实现过程的理解。

实验内容▪在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简单的单用户文件系统。

在退出这个简单文件系统时,应将该虚拟文件系统保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘上。

▪文件存储空间的分配可以采用显式链接分配或其它方法。

▪空闲空间的管理可以选择位示图或其它方法。

如果采用位示图来管理文件存储空间,并采用显式链接分配方式,可以将位示图合并到FAT中。

▪文件目录结构采用多级目录结构。

为简单起见,可以不使用索引结点,其中的每个目录项包含文件名、物理地址、文件长度等信息,还可以通过目录项实现对文件读和写的保护。

▪要求提供以下有关的文件操作:✧Format:对文件存储器进行格式化,即按照文件系统的结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。

✧Mkdir:用于创建子目录。

✧Rmdir:用于删除子目录。

✧Ls:用于显示目录。

✧Cd:用于更改当前目录。

✧Create:用于创建文件。

✧Open:用于打开文件。

✧Close:用于关闭文件。

✧Write:用于写文件。

✧Read:用于读文件。

✧Rm:用于删除文件。

数据结构设计磁盘:整个磁盘为一个char数组,数组中的每一个元素当做是一个扇区,每个扇区可以存储1个字节的信息,簇大小为8字节。

FAT表:存储的是指定编号的簇的下一个簇的编号是什么,因为文件是有可能分散在很多的簇里。

文件和文件夹链表:设计为静态链表,每个文件夹都会有一个子目录列表,存在链表中。

文件和目录表:文件和目录相同对待,信息存放在文件目录表中,为一个数组类型。

以上所有的信息存放在一个fs结构体中,所有的结构都为静态实现,所以需要将文件系统存放到磁盘中的时候只需要将整个结构体以二进制性质存放到文件中或者是将从文件中以二进制形式读取。

主要功能实现:Format:清空文件目录表和fat表以及磁盘数组中的所有内容。

Mkdir:首先创建一个目录表项,初始化之后插入到父目录的子目录表中。

Rmdir:利用递归,递归删除当前目录的所有子目录和当前目录本身。

Ls:打印当前的子目录表中的所有内容。

Cd:利用子目录指针寻找目录。

Create:首先在磁盘中申请相应多的簇,然后将信息写入到簇中。

并且在文件目录表中创建一个文件项,并且插入到父目录的子目录表中。

Open:找到文件并且根据fat表打印簇的内容Rm:通过fat表释放簇空间,并且从父目录的表中删除文件。

源代码FS.h#ifndef __FS_ROLL___#define __FS_ROLL___//包含所需的头文件以及宏定义#include <stdio.h>#include <string.h>#include <stdlib.h>#define DISK_SIZE (480 * 1024) //480KB#define BLOCK_SIZE 8 //簇大小#define BLOCK_CNT (DISK_SIZE / BLOCK_SIZE)#define MAX_NAME_LEN 128 //文件名最大长度#define MAX_FILE_CNT 1024 //最多文件个数typedef unsigned int uint; //簇编号//FAT表结构typedef struct FAT {uint next;} FAT;typedef struct List {uint fid, next, prev;} List;typedef enum { File, Directory, Empty } Type;typedef struct File_Type {Type type;char name[MAX_NAME_LEN];char path[MAX_NAME_LEN << 4];union {uint sublist;uint str_pos;};union {uint parid;uint fsize;};} UFD;typedef struct {char disk[DISK_SIZE];uint fpos, flpos;FAT fat[BLOCK_CNT];UFD ufd[MAX_FILE_CNT];List ulist[MAX_FILE_CNT];} FS;void writeToFile(FS *fs, const char *file_name); //将整个磁盘映像写入文件FS *readFromFile(const char *file_name); //从文件中读取磁盘映像FS *createFileSystem(); //创建磁盘void format(FS *fs); //格式化磁盘uint newSubListNode(FS *fs); //新建一个链表节点uint newUFDNode(FS *fs); //新建一个UFD节点void addNode(FS *fs, uint hid, uint node); //添加节点void makeDIR(FS *fs, uint nowfd, const char *dir_name); //创建目录void Ls(FS *fs, uint nowfd); //显示当前目录下面所有文件void Cd(FS *fs, const char *path, int *nowfd); //进入目录int searchPath(FS *fs, const char *argv); //按照绝对路径查找int searchFile(FS *fs, int nowfd, Type type, const char *name); //在当前目录下面搜索文件void createFile(FS *fs, int nowfd, const char *name, const char *buf, int buf_size); //创建文件uint alloc(FS *fs, uint size); //分配簇uint findNextSpace(FS *fs, int spos); //查找下一个空闲簇void writeToDisk(FS *fs, uint str_pos, char *buf, int buf_size); //将文件内容写入到簇中uint calcAddr(uint blockid); //计算簇位置和扇区位置换算void Cat(FS *fs, int nowfd, const char *file_name); //查看文件void outputBlock(FS *fs, int bid); //输出一个簇中的内容void RmFile(FS *fs, int nowfd, const char *file_name); //删除文件void RmDIR(FS *fs, int nowfd, const char *file_name); //递归删除文件和所有文件夹void clearBlock(FS *fs, uint str_pos); //清空一段连续的簇#endifFS.c#include "FS.h"void clearBlock(FS *fs, uint str_pos) {uint now = fs->fat[str_pos].next, p = str_pos;fs->fat[p].next = -1;for(;now != str_pos; now = p) {p = fs->fat[now].next;fs->fat[now].next = -1;}}void RmFile(FS *fs, int nowfd, const char *file_name) {printf("正在删除文件%s\n", file_name);if(searchFile(fs, nowfd, File, file_name) == -1) {puts("文件不存在");return;}UFD *nowdir = &(fs->ufd[nowfd]), *nowp;int i;for(i = fs->ulist[nowdir->sublist].next; i != nowdir->sublist; i = fs->ulist[i].next) {nowp = &(fs->ufd[fs->ulist[i].fid]);if(nowp->type != File) continue;if(strcmp(nowp->name, file_name) != 0) continue;//删除文件并且清除扇区clearBlock(fs, nowp->str_pos);nowp->type = Empty;fs->ulist[fs->ulist[i].prev].next = fs->ulist[i].next;fs->ulist[fs->ulist[i].next].prev = fs->ulist[i].prev;fs->ulist[i].fid = -1;fs->ulist[i].prev = fs->ulist[i].next = i;break;}}void RmDIR(FS *fs, int nowfd, const char *file_name) {printf("正在删除文件夹%s\n", file_name);int fcid;if((fcid = searchFile(fs, nowfd, Directory, file_name)) == -1) {puts("目录不存在"); return;}//将当前目录从父目录的儿子中删除UFD *nowdir = &(fs->ufd[nowfd]), *nowp;int i;for(i = fs->ulist[nowdir->sublist].next; i != nowdir->sublist; i = fs->ulist[i].next) { nowp = &(fs->ufd[fs->ulist[i].fid]);if(nowp->type != Directory) continue;if(strcmp(nowp->name, file_name) != 0) continue;fs->ulist[fs->ulist[i].prev].next = fs->ulist[i].next;fs->ulist[fs->ulist[i].next].prev = fs->ulist[i].prev;fs->ulist[i].fid = -1;fs->ulist[i].prev = fs->ulist[i].next = i;break;}//删除目录下的所有文件和文件夹while(fs->ulist[fs->ufd[fcid].sublist].next != fs->ufd[fcid].sublist) {int nowid = fs->ulist[fs->ulist[fs->ufd[fcid].sublist].next].fid;if(fs->ufd[nowid].type == File) RmFile(fs, fcid, fs->ufd[nowid].name);else RmDIR(fs, fcid, fs->ufd[nowid].name);}fs->ufd[fcid].type = Empty;fs->ulist[fs->ufd[fcid].sublist].fid = -1;}void outputBlock(FS *fs, int bid) {int i, spos = bid * BLOCK_SIZE;for(i = 0; i < BLOCK_SIZE && fs->disk[spos + i] != 0; i++) {putchar(fs->disk[spos + i]);}}void Cat(FS *fs, int nowfd, const char *file_name) {uint fid;if((fid = searchFile(fs, nowfd, File, file_name)) == -1) {puts("要查看的文件不存在");return;}int now = fs->ufd[fid].str_pos;outputBlock(fs, now);for(now = fs->fat[now].next; now != fs->ufd[fid].str_pos; now = fs->fat[now].next) { outputBlock(fs, now);}puts("");}uint calcAddr(uint blockid) {return blockid * BLOCK_SIZE;}uint findNextSpace(FS *fs, int spos) {spos++;while(fs->fat[spos].next != -1) {spos = (spos + 1) % BLOCK_CNT;}return spos;}uint alloc(FS *fs, uint size) {int nowsize = 0, str_pos = findNextSpace(fs, 0), now = str_pos;fs->fat[now].next = now;nowsize = BLOCK_SIZE;while(nowsize < size) {nowsize += BLOCK_SIZE;fs->fat[now].next = findNextSpace(fs, now);now = fs->fat[now].next;fs->fat[now].next = str_pos;}return (uint)str_pos;}void writeToDisk(FS *fs, uint str_pos, char *buf, int buf_size) {strncpy(&(fs->disk[calcAddr(str_pos)]), buf, BLOCK_SIZE);int now = fs->fat[str_pos].next;while(now != str_pos) {buf += BLOCK_SIZE;strncpy(&(fs->disk[calcAddr(now)]), buf, BLOCK_SIZE);now = fs->fat[now].next;}}void createFile(FS *fs, int nowfd, const char *name, const char *buf, int buf_size) { //判断文件是否存在if(searchFile(fs, nowfd, File, name) != -1) {puts("文件已存在,无法创建");return;}uint newfid = newUFDNode(fs), newflid = newSubListNode(fs);UFD *newNode = &(fs->ufd[newfid]);List *newLNode = &(fs->ulist[newflid]);newLNode->fid = newfid;newNode->type = File;strcpy(newNode->name, name);strcpy(newNode->path, fs->ufd[nowfd].path);strcat(newNode->path, name);newNode->fsize = buf_size;newNode->str_pos = alloc(fs, buf_size);writeToDisk(fs, newNode->str_pos, buf, buf_size);addNode(fs, fs->ufd[nowfd].sublist, newflid);}void writeToFile(FS *fs, const char *file_name) {FILE *fp = fopen(file_name, "wb+");printf("%x\n", fp);fwrite((void *)fs, sizeof(FS), 1, fp);fclose(fp);printf("写入%d字节完成\n", (int)(sizeof(FS)));}FS *readFromFile(const char *file_name) {FILE *fp = fopen(file_name, "rb+");printf("%x\n", fp);FS *fs = (FS *)malloc(sizeof(FS));fread((void *)fs, sizeof(FS), 1, fp);fclose(fp);return fs;}int searchFile(FS *fs, int nowfd, Type type, const char *name) {UFD *nowdir = &(fs->ufd[nowfd]), *nowp;int i;//遍历所有子文件夹for(i = fs->ulist[nowdir->sublist].next; i != nowdir->sublist; i = fs->ulist[i].next) { nowp = &(fs->ufd[fs->ulist[i].fid]);if(nowp->type != type) continue;if(strcmp(nowp->name, name) == 0) return fs->ulist[i].fid;}return -1;}int searchPath(FS *fs, const char *argv) {int i;for(i = 0; i < MAX_FILE_CNT; i++) if(fs->ufd[i].type != Empty) {if(strcmp(argv, fs->ufd[i].path) == 0) {return i;}}return -1;}void Cd(FS *fs, const char *argv, int *nowfd) {UFD *nowdir = &(fs->ufd[*nowfd]), *nowp;//如果是返回上一级目录if(strcmp(argv, "..") == 0) {if(nowdir->parid == -1) {puts("当前目录已经是根目录,不能向上");return;}*nowfd = nowdir->parid;return;}//如果是绝对路径else if(argv[0] == '\\') {int tmp = searchPath(fs, argv);if(tmp == -1) {puts("未找到路径");return;}*nowfd = tmp;return;}else {int i;//遍历所有子文件夹for(i = fs->ulist[nowdir->sublist].next; i != nowdir->sublist; i = fs->ulist[i].next) { nowp = &(fs->ufd[fs->ulist[i].fid]);if(nowp->type == File) continue;if(strcmp(nowp->name, argv) == 0) break;}if(i == nowdir->sublist) {puts("未找到该文件夹");}else {printf("find i = %d\n", i);*nowfd = fs->ulist[i].fid;}}}void addNode(FS *fs, uint hid, uint node) {List *newNode = &(fs->ulist[node]), *h = &(fs->ulist[hid]);newNode->prev = h->prev;newNode->next = hid;fs->ulist[h->prev].next = node;h->prev = node;}void Ls(FS *fs, uint nowfd) {UFD *nowdir = &(fs->ufd[nowfd]), *nowp;int i, cnt = 0;puts("当前目录下的文件和文件夹有:");for(i = fs->ulist[nowdir->sublist].next; i != nowdir->sublist; i = fs->ulist[i].next) { nowp = &(fs->ufd[fs->ulist[i].fid]);printf("%s\t\t\t\t%s\n", nowp->name, nowp->type == File ? "文件" : "文件夹");cnt++;}printf("总计%d个\n", cnt);}void makeDIR(FS *fs, uint nowfd, const char *dir_name) {if(searchFile(fs, nowfd, Directory, dir_name) != -1) {puts("文件夹已存在,不能创建");return;}UFD *nowdir = &(fs->ufd[nowfd]);int newfid = newUFDNode(fs), newflid = newSubListNode(fs);UFD *newdir = &(fs->ufd[newfid]);List *newnode = &(fs->ulist[newflid]);//初始化信息newdir->type = Directory;strcpy(newdir->name, dir_name);strcpy(newdir->path, nowdir->path);strcat(newdir->path, dir_name);strcat(newdir->path, "\\");newdir->parid = nowfd;newnode->fid = newfid;newnode->next = newnode->prev = newflid;int newsubflid = newSubListNode(fs);List *newsubnode = &(fs->ulist[newsubflid]);newsubnode->fid = newfid;newsubnode->next = newsubnode->prev = newsubflid;newdir->sublist = newsubflid;//将新的文件夹添加到父文件夹的列表中addNode(fs, nowdir->sublist, newflid);}FS *createFileSystem() {FS *fs = (FS *)malloc(sizeof(FS));return fs;}uint newSubListNode(FS *fs) {int i = fs->flpos;while(fs->ulist[i].fid != -1) i = (i + 1) % MAX_FILE_CNT;return fs->flpos = i;}uint newUFDNode(FS *fs) {int i = fs->fpos;while(fs->ufd[i].type != Empty) i = (i + 1) % MAX_FILE_CNT;return fs->fpos = i;}void format(FS *fs) {int i;//清空磁盘memset(fs->disk, 0, sizeof(fs->disk));//初始化FATfor(i = 0; i < BLOCK_CNT; i++) fs->fat[i].next = -1;//初始化文件链表for(i = 0; i < MAX_FILE_CNT; i++) {fs->ulist[i] = (List) {-1, i, i};}//初始化UFDfs->fpos = fs->flpos = 0;for(i = 0; i < MAX_FILE_CNT; i++) {fs->ufd[i].type = Empty;}//创建根目录UFD *root = &(fs->ufd[newUFDNode(fs)]);root->name[0] = 0;strcpy(root->path, "\\");root->type = Directory;root->parid = -1;uint g = root->sublist = newSubListNode(fs);fs->ulist[g].fid = 0;fs->ulist[g].next = fs->ulist[g].prev = g;}main.c#include <stdio.h>#include <stdlib.h>#include "fs.h"char buf[1024];int main(){char cmd[128], arg[256];FS *fs = createFileSystem();format(fs);int nowfd = 0;while(scanf("%s", cmd) != EOF) {if(strcmp(cmd, "ls") == 0) {Ls(fs, nowfd);}else if(strcmp(cmd, "mkdir") == 0) {scanf("%s", arg);makeDIR(fs, nowfd, arg);}else if(strcmp(cmd, "cd") == 0) {scanf("%s", arg);Cd(fs, arg, &nowfd);}else if(strcmp(cmd, "quit") == 0) {break;}else if(strcmp(cmd, "write") == 0) {writeToFile(fs, "test.img");}else if(strcmp(cmd, "read") == 0) {free(fs);fs = readFromFile("test.img");nowfd = 0;}else if(strcmp(cmd, "create") == 0) {scanf("%s", arg);getchar();printf("请输入文件内容: ");gets(buf);createFile(fs, nowfd, arg, buf, strlen(buf)); }else if(strcmp(cmd, "cat") == 0) {scanf("%s", arg);Cat(fs, nowfd, arg);}else if(strcmp(cmd, "rm") == 0) {scanf("%s", arg);RmFile(fs, nowfd, arg);}else if(strcmp(cmd, "rmdir") == 0) {scanf("%s", arg);RmDIR(fs, nowfd, arg);}else if(strcmp(cmd, "format") == 0) {format(fs);}printf("当前路径: %s\n", fs->ufd[nowfd].path);/*for debugprintf("%d %d\n", fs->fpos, fs->flpos);int i;for(i = 0; i <= fs->flpos; i++) {printf("%d %d %d-->", fs->ulist[i].fid, fs->ulist[i].prev, fs->ulist[i].next);}puts("");printf("nowfd = %d\n", nowfd);*/}//writeToFile(fs, "test.img");return 0;}运行截图Cd,mkdir和ls命令创建和打开文件删除文件夹:。

相关主题