资源描述
评定等级
操作系统课程设计
文件系统管理
学院计算机学院
专业计算机科学与技术
班级
姓名
学号
2013年1月8日
广东工业大学计算机学院制
文件系统管理
一、实验目的
模拟文件系统的实现的基本功能,了解文件系统的基本结构和文件系统的管理方法看,加深了解文件系统的内部功能的实现。通过高级语言编写和实现一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作系统命令的实质内容和执行过程有比较深入的了解。
二、实验内容和要求
编程模拟一个简单的文件系统,实现文件系统的管理和控制功能。在用户程序中通过使用文件系统提供的create,open,read,write,close,delete等文件命令,对文件进行操作。
以下报告主要包括:
1.可行性分析
2。需求分析
3。概要设计
4。详细设计
5。测试
6.总结
三、可行性分析
1、技术可行性
对于图形编程还不了解,但是经过本学期的三次实验的练习,可以设计好命令操作界面.利用大二期间学习的数据结构可以模拟出此课程设计的要求。
2、经济可行性
课程设计作为本课程的练习及进一步加深理解.与经济无关,可以不考虑。(零花费,零收益)
3。法律可行性
自己编写的程序,仅为练习,不作其他用途,与外界没什么联系,可行。
四、需求分析
编写程序实现文件系统,主要有以下几点要求:
1、实现无穷级目录管理及文件管理基本操作
2、实现共享“别名”
3、加快了文件检索
五、概要设计
为了克服单级目录所存在的缺点,可以为每一位用户建立一个单独的用户文件目录UFD(User File Directory).这些文件目录可以具有相似的结构,它由用户所有文件的文件控制块组成。此外,在系统中再建立一个主文件目录MFD (Master File Directory);在主文件目录中,每个用户目录文件都占有一个目录项,其目录项中包括用户名和指向该用户目录的指针。
本设计主要实现下面几个数据结构:
M D F
用户名
文件目录指针
用户名
文件目录指针
U F D
文件名
保护码
文件长度
文件名
·
·
·
A F D
打开文件名
打开保护码
读写指针
总体的流程图如下:
六、详细设计
主要数据结构:
1。MFD(Master File Directory),主要用以存放用户,可以增加存放密码的字符数组,本设计没有保密安全方面的忧虑,为了使用时操作更简单省去密码.所以,MFD结构仅包括用户名和指向子目录的一个指针,以及指向下一用户的连接点,为线性结构。
struct MFD
{
char name[20]; //用户名
UFD *bst_pointer; //文件目录指针
MFD *link;
};
2. UFD(User File Directory),用于存放文件的数据结构.由于本设计为了加快检索速度,使用了二叉排序树的结构,所以UFD结构中相应加入了用于树结构的parent,leftchild,和rightchild记录链接情况.
当本文件为普通文件时,为下级记录申请AFD(file),folder为空.同样,当本文件为文件夹时,为它申请相应的空间,AFD为空.以此来达到无穷级别目录的存储.
struct UFD
{
UFD *parent;
UFD *leftchild;
UFD *rightchild;
UFD *folder; //作为文件夹时指向下一层,文件时为空
UFD *pre_folder; //指向上一层目录(文件夹时用到)
AFD *file; //作文文件时文件的具体内容
char name[30]; //文件(夹)名字
int length; //作为文件时文件的长度,默认为0
char rw; //读写标志r or w
char share; //共享标志y or n
char file_folder; //指示此文件是文件或文件夹,f为文件,o为文件夹
};
3.AFD,存放文件的内容的结构,比较简单,文件内容用一个字符数组存储,为顺序结构,最多可存放99个字符
struct AFD
{
char afd_file[100];
int read; //读指针
int write; //写指针
};
4.REC
struct REC //UFD的线性链,用于记录共享文件和已打开文件
{
UFD *file;
REC *link;
};
关键函数说明:
void Log_in(); //登陆
void Init_user(); //创建用户
void Check_user(); //查看用户
以上三个函数为开始时管理用户创建和登陆的函数。开始时没有用户,需要创建后才可登陆。创建用户即自动分配一个存放用户文件的UFD,此时的UFD为空,需要后续的创建文件以及文件夹的分配.
UFD *operations(UFD *fileBST); //文件夹的操作调用
用户登陆后即开始对该用户文件UFD的操作,同时,若在文件夹中创建一个文件夹,它同样可以分配得到一个UFD,对用户文件的操作可以重复调用,以此来达到无穷级目录的操作.在里层文件的操作和外层的是一样的,但若要退回外层文件夹就需要逐层返回,不能立即跳到某一层某地址。操作完毕后返回改变后的文件存储状态。
void fcreate(UFD *fileBST); //对文件夹的六个基本操作
UFD *fdelete(UFD *fileBST);
void fopen(UFD *fileBST);
void fclose(UFD *fileBST);
void fread_write(UFD *fileBST,char f); //读写操作。按选择f=5为读6为写
以上五个函数为对文件的六个基本操作,其中读文件和写文件部分代码相同,所以由一个函数完成。在create五个函数中,分别对文件夹fileBST做了相应的处理,由于删除文件的函数可能会删除到头结点,所以需要一个返回值。
void insertBST(UFD *fileBST,UFD *newBST); //在fileBST中插入新的结点newBST
UFD *searchBST(UFD *fileBST,char name); //在fileBST树中查找名字为name的结
//点并返回该结点,文件不存在则返回空
void BSTtraverse(UFD *fileBST); //遍历二叉树
UFD *deleteBST(UFD *fileBST,char name[30]); //删除name结点,返回删除后的结点
由于该设计的存储结构用到了二叉排序树,所以把相关的操作写成函数,供基本操作的函数调用.insert函数在fileBST中插入新的结点newBST;search函数在fileBST树中查找名字为name的结点并返回该结点,文件不存在则返回空;还有traverse和delete函数对二叉排序树做了基本的操作。
void print_path(UFD *fileBST); //输出当前路径
void print_open_file(); //输出已打开的文件
为了在文件系统中使用户看出路径及一些相关的状态,设置了输出文件路径的函数,路径由每个文件的结构体中pre_folder记录上一层的文件夹名字,这样逐层输出即可达到目的。
每执行一次操作就输出一次已打开的文件的具体情况,打开的文件应及时关闭,否则删除时会有删除失败提示。
UFD *check_share(char name[30]); //在共享链中检查是否有name文件,有则//返回该UFD,没则NULL
void del_in_share(UFD *node); //在共享链中删除node结点
以上两个函数为对共享文件的处理函数,当打开或读写文件时在本层文件中未找到相应的文件时,就用check_share函数在共享文件中查找,如果存在就返回该文件的UFD,不存在就返回NULL,而del_in_share函数是伴随着删除文件的函数出现的,目的是为了删除文件以后不会在共享链中再存在。
具体代码如下:
filesysterm。h
struct AFD
{
char afd_file[100];
int read; //读指针
int write; //写指针
};
struct UFD
{
UFD *parent;
UFD *leftchild;
UFD *rightchild;
UFD *folder; //作为文件夹时指向下一层,文件时为空
UFD *pre_folder; //指向上一层目录(文件夹时用到)
AFD *file; //作文文件时文件的具体内容
char name[30]; //文件(夹)名字
int length; //作为文件时文件的长度,默认为0
char rw; //读写标志r or w
char share; //共享标志y or n
char file_folder; //指示此文件是文件或文件夹,f为文件,o为文件夹
};
struct MFD
{
char name[20]; //用户名
UFD *bst_pointer; //文件目录指针
MFD *link;
};
struct REC //UFD的线性链,用于记录共享文件和已打开文件
{
UFD *file;
REC *link;
};
void Log_in(); //登陆
void Init_user(); //创建用户
void Check_user(); //查看用户
UFD *operations(UFD *fileBST); //文件夹的操作调用,user不为空时为第一层
void fcreate(UFD *fileBST); //对文件夹的六个基本操作
UFD *fdelete(UFD *fileBST);
void fopen(UFD *fileBST);
void fclose(UFD *fileBST);
void fread_write(UFD *fileBST,char f); //代码有重复,合并读写操作。按选择s=5为读6为写
void insertBST(UFD *fileBST,UFD *newBST); //新文件插入到user文件树中
UFD *searchBST(UFD *fileBST,char name); //在fileBST树中查找名字为name的结点并返回该结点
//文件不存在则返回空
void BSTtraverse(UFD *fileBST); //遍历二叉树
UFD *deleteBST(UFD *fileBST,char name[30]); //删除成功返回1,失败返回0
void print_path(UFD *fileBST); //输出当前路径
void print_open_file(); //输出已打开的文件
UFD *check_share(char name[30]); //在共享链中检查是否有name文件,有则返回UFD,没则NULL
void del_in_share(UFD *node); //在共享链中删除node结点
main.cpp
#include 〈iostream>
#include〈conio。h>
#include"filesystem.h”
MFD *mfd_link=NULL; //用户链表
MFD *pre_user; //当前操作用户
UFD *pre_opera_folder=NULL;//当前操作文件夹
int folder_depth=0; //记录当前文件深度(用于辅助pre_folder的初始化)
REC *share_file=NULL;
REC *open_file=NULL;
void print_path(UFD *fileBST) //输出路径
{
if(fileBST—〉pre_folder!=NULL)
{ print_path(fileBST—〉pre_folder);
printf(”/%s”,fileBST—>pre_folder—〉name);
}
else
printf("/%s",pre_user—>name);
}
void print_open_file()
{
REC *temp;
int i=5;
temp=open_file;
while(temp!=NULL)
{
printf("%s\t%d\t\t",temp->file—>name,temp—〉file—>length);
if(temp-〉file-〉rw==’r’)printf("只读\t”);
else printf("可读写\t”);
if(temp-〉file-〉share=='y’)printf("是\t”);
else printf("否\t”);
for(i=0;i〈5;i++)
{
if(temp—〉file—〉file—>afd_file[i]!=’\0’)
printf("%c”,temp—>file—〉file—>afd_file[i]);
else break;
}
if(temp—〉file—〉file-〉afd_file[i]!='\0’&&i==5) printf("。。”);
printf(”\n”);
temp=temp—>link;
}
}
void BSTtraverse(UFD *fileBST) //遍历二叉树(前序遍历)
{
UFD *left,*right;
printf(”%s”,fileBST—>name);
if(fileBST—〉file_folder==’o’) //输出。。以区分文件夹
printf(”。。\t”);
else
printf(”\t”);
if(fileBST—〉leftchild!=NULL) //递归
{
left=fileBST—>leftchild;
BSTtraverse(left);
}
if(fileBST—〉rightchild!=NULL)
{
right=fileBST—〉rightchild;
BSTtraverse(right);
}
}
UFD *searchBST(UFD *fileBST,char name[30])//在fileBST树中查找名字为name的结点并返回该结点
{ //文件不存在则返回空
int flag;
flag=strcmp(fileBST-〉name,name);
if(flag==0)
return fileBST; //查找成功
else if(flag>0)
{
if(fileBST-〉leftchild==NULL) return NULL; //查找失败
else
searchBST(fileBST—>leftchild,name); //递归调用
}
else
{
if(fileBST-〉rightchild==NULL) return NULL;
else
searchBST(fileBST—>rightchild,name);
}
}
void insertBST(UFD *fileBST,UFD *newBST) //将结点newBST插入原二叉树fileBST中
{
int flag;
flag=strcmp(fileBST-〉name,newBST-〉name);
if(flag〉0)
{
if(fileBST—>leftchild==NULL) //插入
{
fileBST->leftchild=newBST;
newBST-〉parent=fileBST;
}
else
insertBST(fileBST—〉leftchild,newBST); //递归调用
}
else
{
if(fileBST—>rightchild==NULL) //插入
{
fileBST—〉rightchild=newBST;
newBST-〉parent=fileBST;
}
else
insertBST(fileBST->rightchild,newBST); //递归调用
}
/*flag=0 的情况已在创建时排除*/
}
UFD *deleteBST(UFD *fileBST,char name[30])//删除名字问name的文件结点
{
UFD *parent_file=NULL,*del_file=NULL;
UFD *move_file=NULL,*move_file_parent;
del_file=searchBST(fileBST,name);
if(del_file==NULL)
{
printf("没有此文件,删除失败!\n”);
getch();
return fileBST; //查找失败
}
if(del_file-〉file_folder==’o'&&strcmp(del_file-〉folder—〉name,”NULL”)!=0)
{ printf(”注意,本系统未能实现级联删除,请先逐个删除文件!");
printf(”文件夹非空,删除失败!\n”);
getch();
return fileBST;
}
if(del_file—〉share==’y’) //先在共享链中删除
del_in_share(del_file);
parent_file=del_file-〉parent;
if(del_file—〉leftchild==NULL&&del_file—>rightchild==NULL) //被删除结点为子叶结点
{
if(del_file==fileBST) //只有一个结点
{
strcpy(fileBST-〉name,"NULL");
}
else if(parent_file—〉leftchild==del_file)
{
parent_file—〉leftchild=NULL;
free(del_file);
}
else
{
parent_file—〉rightchild=NULL;
free(del_file);
}
}
else if(del_file-〉leftchild==NULL||del_file-〉rightchild==NULL) //被删除结点没有做孩子或右孩子
{
if(del_file—>leftchild==NULL) //没有左孩子
{
if(parent_file==NULL)//删除的为根结点
{
fileBST=del_file-〉rightchild;
del_file—>rightchild—〉parent=NULL;
}
else if(parent_file—>leftchild==del_file) //右孩子接上
{
parent_file->leftchild=del_file—>rightchild;
del_file-〉rightchild—〉parent=parent_file;
}
else //右孩子接上
{
parent_file—〉rightchild=del_file-〉rightchild;
del_file-〉rightchild—〉parent=parent_file;
}
}
else //没有右孩子
{
if(parent_file==NULL)//删除的为根结点
{
fileBST=del_file-〉leftchild;
del_file—〉leftchild—〉parent=NULL;
}
else if(parent_file—〉leftchild==del_file) //左孩子接上
{
parent_file—〉leftchild=del_file—>leftchild;
del_file—〉leftchild->parent=parent_file;
}
else //左孩子接上
{
parent_file->rightchild=del_file—〉leftchild;
del_file—〉leftchild—〉parent=parent_file;
}
}
free(del_file);
}
else //左右孩子都有
{
move_file_parent=del_file-〉leftchild;
move_file=move_file_parent—〉rightchild;
if(move_file==NULL) //被删除结点的左孩子没有右孩子
{
if(parent_file==NULL) //删除的为根结点
{
fileBST=move_file_parent;
fileBST-〉rightchild=del_file—>rightchild;
fileBST->parent=NULL;
}
else if(parent_file-〉leftchild==del_file)
parent_file-〉leftchild=move_file_parent;
else
parent_file—〉rightchild=move_file_parent;
move_file_parent—>parent=parent_file;
move_file_parent—>rightchild=del_file—>rightchild;
}
else
{
while(move_file—〉rightchild!=NULL) //寻找右边最底下的结点
{
move_file=move_file—〉rightchild;
move_file_parent=move_file_parent->rightchild;
}
move_file_parent—>rightchild=NULL;
move_file-〉leftchild=del_file-〉leftchild;
move_file—〉rightchild=del_file—>rightchild;
if(move_file-〉rightchild!=NULL)
move_file—>rightchild->parent=move_file; //右孩子的双亲也要改变
move_file->parent=del_file—>parent;
if(fileBST==del_file) //删除的为根结点
fileBST=move_file;
free(del_file);
}
}
printf(”成功删除文件%s\n",name);
getch();
return fileBST;
}
void del_in_share(UFD *node)
{
REC *first,*second;
first=share_file;
second=share_file->link;
if(second==NULL)
{share_file=NULL;free(first);}
else
do
{
if(second—〉file==node)
{first-〉link=second—〉link;free(second);}
else
{
first=first—>link;
second=second—〉link;
}
}while(second!=NULL);
}
void fcreate(UFD *fileBST) //在fileBST的同一层创建文件
{
char s;
char name[30];
int flag=0;
UFD *newfile,*temp=NULL;
REC *stemp;
system(”cls”);
printf(”—-——------——-——--———-————————-—-—-——-———-—---—--—--————————-——--\n”);
printf("————-—------——--—-- 文 件 系 统/创 建 文 件-—————-——————----——-—\n”);
printf(”—--—----————--—--—--———————-———————-——-——-—-——--—————-—---—-—-—-\n\n”);
do
{
printf(” 1。 创建文件 \n”);
printf(" 2. 创建文件夹 \n");
printf(” 3. 取消 \n”);
printf(”请选择:\n");
scanf("%c”,&s);
fflush(stdin);
if(s==’3')return;
if(s!=’1’&&s!=’2’)
printf(”输入错误,请重新输入!\n");
}while(s!='1’&&s!='2’);
if(strcmp(fileBST—〉name,"NULL”)==0) //节点已有(未赋值)用于本层文件夹的第一个文件的特殊情况
newfile=fileBST;
else{
newfile=(UFD*)malloc(sizeof(UFD)); //创建树节点
newfile—〉leftchild=NULL;
newfile—>rightchild=NULL;
}
printf(”请输入文件(夹)名:”);
scanf(”%s”,name);
fflush(stdin);
//搜索二叉树,文件重名就创建失败
temp=searchBST(fileBST,name);
if(temp!=NULL)
{
printf(”已存在该文件(夹),创建失败!\n”);
strcpy(newfile—>name,”NULL");
return;
}
strcpy(newfile—〉name,name);
if(folder_depth==1)
newfile-〉pre_folder=NULL;
else
newfile—〉pre_folder=pre_opera_folder;//指向正在操作文件夹
while(1) //读写否,共享否
{
printf(”只读r还是可读写w:");
scanf(”%c”,&(newfile-〉rw));
fflush(stdin);
printf(”是否共享y/n:”);
scanf("%c”,&(newfile—〉share));
fflush(stdin);
if((newfile—〉rw==’r’||newfile—>rw=='w')&&(newfile—>share=='y'||newfile—〉share=='n’))
break;
printf(”输入有误,请重新输入!\n”);
}
//***********以下为文件和文件夹初始化中不同的地方******************
if(s==’1’)
{
newfile—>file_folder='f';
newfile—〉folder=NULL;
newfile—>file=(AFD*)malloc(sizeof(AFD));
printf("请输入文件的内容(<100):”);
scanf(”%s”,newfile—〉file-〉afd_file);
fflush(stdin);
newfile-〉length=str
展开阅读全文