简单文件系统的实现实验报告.docx
《简单文件系统的实现实验报告.docx》由会员分享,可在线阅读,更多相关《简单文件系统的实现实验报告.docx(14页珍藏版)》请在冰豆网上搜索。
![简单文件系统的实现实验报告.docx](https://file1.bdocx.com/fileroot1/2022-12/6/61007993-69e6-4026-9eac-fffd9d195b1a/61007993-69e6-4026-9eac-fffd9d195b1a1.gif)
简单文件系统的实现实验报告
操作系统课程设计报告
简单文件系统的实现
专业:
班级:
姓名:
学号:
老师:
一、课程设计的目的
1.通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部数据结构、功能以及实现过程的理解。
二、课程设计要求
1.在内存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统中的文件系统。
在退出该文件系统的使用时,应将该虚拟文件系统以一个Windows文件的方式保存到磁盘上,以便下次可以再将它恢复到内存的虚拟磁盘空间中。
2文件存储空间的分配可采用显式链接分配或其他的办法。
3空闲磁盘空间的管理可选择位示图或其他的办法。
如果采用位示图来管理文件存储空间,并采用显式链接分配方式,那么可以将位示图合并到FAT中。
文件目录结构采用多级目录结构。
为了简单起见,可以不使用索引结点,其中的每个目录项应包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护。
要求提供以下有关的操作命令:
my_format:
对文件存储器进行格式化,即按照文件系统的结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。
my_mkdir:
用于创建子目录。
my_rmdir:
用于删除子目录。
my_ls:
用于显示目录中的内容。
my_cd:
用于更改当前目录。
my_create:
用于创建文件。
my_open:
用于打开文件。
my_close:
用于关闭文件。
my_write:
用于写文件。
my_read:
用于读文件。
my_rm:
用于删除文件。
my_exitsys:
用于退出文件系统。
三、程序的设计细想和框图
1.打开文件函数fopen()
(1)格式:
FILE*fopen(constchar*filename,constchar*mode)
(2)功能:
按照指定打开方式打开指定文件。
(3)输入参数说明:
filename:
待打开的文件名,如果不存在就创建该文件。
mode:
文件打开方式,常用的有:
"r":
为读而打开文本文件(不存在则出错)。
"w":
为写而打开文本文件(若不存在则创建该文件;反之,则从文件起始位置写,原内容将被覆盖)。
"a":
为在文件末尾添加数据而打开文本文件。
(若不存在则创建该文件;反之,在原文件末尾追加)。
"r+":
为读和写而打开文本文件。
(读时,从头开始;在写数据时,新数据只覆盖所占的空间,其后不变)。
"w+":
首先建立一个新文件,进行写操作,随后可以从头开始读。
(若文件存在,原内容将全部消失)。
"a+":
功能与"a"相同;只是在文件末尾添加新的数据后,可以从头开始读。
另外,上述模式字符串中都可以加一个“b”字符,如rb、wb、ab、rb+、wb+、ab+等组合,字符“b”表示fopen()函数打开的文件为二进制文件,而非纯文字文件。
(4)输出:
一个指向FILE类型的指针。
2.关闭文件函数fclose()
(1)格式:
intfclose(FILE*stream);
(2)功能:
用来关闭先前fopen()打开的一个文件。
此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。
(3)输入参数说明:
stream:
指向要关闭文件的指针,它是先前执行fopen()函数的返回值。
(4)输出:
若关闭文件成功则返回0;有错误发生时则返回EOF并把错误代码存到errno。
3.读文件函数fread()
(1)格式:
size_tfread(void*buffer,size_tsize,size_tcount,FILE*stream);
(2)功能:
读二进制文件到内存。
(3)输入参数说明:
buffer:
用于存放输入数据的缓冲区的首地址;
stream:
使用fopen()打开的文件的指针,用于指示要读取的文件;
size:
每个数据块的字节数;
count:
要读入的数据块的个数;
size*count:
表示要求读取的字节数。
(4)输出:
实际读取的数据块的个数。
4.写文件函数fwrite()
(1)格式:
size_tfwite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);
(2)功能:
将数据写到二进制文件中。
(3)输入参数说明:
buffer:
用于存放输出数据的缓冲区的首地址;
stream:
使用fopen()打开的文件的指针,用于指示要写出的文件;
size:
每个数据块的字节数;
count:
要写出的数据块的个数;
size*count:
表示要求写出的字符数。
(4)输出:
实际写出的数据块的个数。
5.判断文件结束函数feof()
(1)格式:
intfeof(FILE*stream)
(2)功能:
用来判断是否已读取到文件末尾。
(3)输入参数说明:
stream:
使用fopen()打开的文件的指针,用于指示要判断的文件。
(4)输出:
如果已读到文件尾则返回非零值,其他情况返回0。
6主要函数功能实现:
intformat();atherBlockNum=-1;ype=GENERAL;
}
}
};
structdirFile/*-------------目录文件结构---------------*/
{
structFCBfcb[BlockFcbCount];
voidinit(int_FatherBlockNum,int_CurrentBlockNum,char*name)name,name);atherBlockNum=_FatherBlockNum;
fcb[0].currentBlockNum=_CurrentBlockNum;
fcb[0].type=DIRECTORY;atherBlockNum=_CurrentBlockNum;ype=Zero;ype==DIRECTORY&&strcmp(dir->fcb[i].fname,sonfname)==0){
printf("该文件夹下已经有同名的文件夹存在了!
\n");
return0;
}
}
for(i=1;ibreak;
}
if(i==BlockFcbCount){
printf("该目录已满!
请选择新的目录下创建!
\n");
return0;
}
temp=i;
for(i=3;iif(osPoint->FAT1[i]==0)
break;
}
if(i==BlockCount){
printf("磁盘已满!
\n");
return0;
}
iFAT=i;
/*-------------接下来进行分配----------*/
osPoint->FAT1[iFAT]=osPoint->FAT2[iFAT]=2;name,sonfname);
dir->fcb[temp].type=DIRECTORY;
dir->fcb[temp].fatherBlockNum=current;
dir->fcb[temp].currentBlockNum=iFAT;
ype==DIRECTORY&&strcmp(dir->fcb[i].fname,sonfname)==0){
break;
}
}
temp=i;
if(i==BlockFcbCount){
printf("当前目录下不存在该子目录!
\n");
return0;
}
j=dir->fcb[temp].currentBlockNum;
structdirFile*sonDir;ype!
=Zero)
{
printf("该文件夹为非空文件夹,为确保安全,请清空后再删除!
\n");
return0;
}
}
/*开始删除子目录操作*/
osPoint->FAT1[j]=osPoint->FAT2[j]=0;nitialize();ype==Zero&&isFound==0){
emptyNum=i;
isFound=1;
}
elseif(dir->fcb[i].type==GENERAL&&strcmp(dir->fcb[i].fname,name)==0){
printf("无法在同一目录下创建同名文件!
\n");
return0;
}
}
if(emptyNum==0){
printf("已经达到目录项容纳上限,无法创建新目录!
\n");
return0;
}
for(i=3;idir->fcb[emptyNum].type=GENERAL;
dir->fcb[emptyNum].fatherBlockNum=current;
dir->fcb[emptyNum].currentBlockNum=iFAT;
dir->fcb[emptyNum].size=0;
char*p=osPoint->data[iFAT-3];
memset(p,4,BlockSize);
printf("在当前目录下创建文本文件成功!
\n");
return1;
}
/*-------查询子目录------------*/
intlistshow()
{
inti,DirCount=0,FileCount=0;
ype==GENERAL){n",dir->fcb[i].fname);
}
if(dir->fcb[i].type==DIRECTORY){n",dir->fcb[i].fname);
}
}
printf("\n该目录下共有%d个文本文件,%d个文件夹\n\n",FileCount,DirCount);
return1;
}
/*---------在当前目录下删除文件-----------*/
intdelfile(char*name)
{
inti,temp,j;
ype==GENERAL&&strcmp(dir->fcb[i].fname,name)==0){
break;
}
}
if(i==BlockFcbCount){
printf("当前目录下不存在该文件!
\n");
return0;
}
intk;
for(k=0;kif((openlist->f[k].type=GENERAL)&&
(strcmp(openlist->f[k].fname,name)==0)){
if(openlist->f[k].fatherBlockNum==current){
break;
}
else{
printf("该文件未在当前目录下!
\n");
return0;
}
}
}
if(k!
=OPEN_MAX){
close(name);
}
urrentBlockNum;nitialize();")==0){
if(current==2){
printf("你现已经在根目录下!
\n");
return0;
}
current=dir->fcb[0].fatherBlockNum;
currentPath=(0,()-strlen(dir->fcb[0].fname)-1);
return1;
}
/*进入子目录*ype==DIRECTORY&&strcmp(dir->fcb[i].fname,sonfname)==0){
temp=i;
break;
}
}
if(i==BlockFcbCount){
printf("不存在该目录!
\n");
return0;
}
urrentBlockNum;
currentPath=currentPath+dir->fcb[temp].fname+"\\";
printf("进入当前目录下的子目录成功!
\n");
return1;
}
intexit(){name,name)==0){
if(openlist->f[i].fatherBlockNum==current){
break;
}
else{
printf("该文件处于打开列表中,本系统只能改写当前目录下文件!
\n");
return0;
}
}
}
if(i==OPEN_MAX){
printf("该文件尚未打开,请先打开后写入信息!
!
\n");
return0;
}
intactive=i;
intfileStartNum=openlist->f[active].currentBlockNum-3;
startPoint=osPoint->data[fileStartNum];
endPoint=osPoint->data[fileStartNum+1];
printf("请输入文本以CtrlD号结束:
\t");
charinput;
while(((input=getchar())!
=4)){
if(startPoint*startPoint++=input;
}
else{
printf("达到单体文件最大容量!
");
*startPoint++=4;
break;
}
}
return1;
}
intread(char*file)/*---------选择一个打开的文件读取信息----------*/
{
inti,fileStartNum;
char*startPoint,*endPoint;
name,file)==0){
if(openlist->f[i].fatherBlockNum==current){
break;
}
else{
printf("该文件处于打开列表中,本系统只能阅读当前目录下文件!
\n");
return0;
}
}
}
if(i==OPEN_MAX){
printf("该文件尚未打开,请先打开后读取信息!
\n");
return0;
}
intactive=i;urrentBlockNum-3;
startPoint=osPoint->data[fileStartNum];
endPoint=osPoint->data[fileStartNum+1];
printf("该文件的内容为:
");
while((*startPoint)!
=4&&(startPointputchar(*startPoint++);
}
printf("\n");
return1;
}
intopen(char*file)ype==GENERAL&&strcmp(openlist->f[i].fname,file)==0
&&openlist->f[i].fatherBlockNum==current)
{
printf("该文件已经被打开!
\n");
return0;
}
}
n");
return0;
}
ype==GENERAL&&strcmp(dir->fcb[i].fname,file)==0){
FcbIndex=i;
break;
}
}
if(i==BlockFcbCount){
printf("当前目录下不存在该文件!
\n");
return0;
}
ype=GENERAL)&&
(strcmp(openlist->f[i].fname,file)==0)){
if(openlist->f[i].fatherBlockNum==current){
break;
}
else{
printf("该文件已打开,但未在当前目录下,无法关闭!
\n");
return0;
}
}
}
if(i==OPEN_MAX){
printf("该文件未在打开列表中!
\n");
return0;
}
intactive=i;
openlist->files--;
openlist->f[active].initialize();
OpenFileCount--;
printf("该文件已关闭!
\n");
return1;
}
intmain()
{
printf("@WelcomeToMyOperateSystemOfFile(FAT)@n");
printf("\n以下是使用说明书:
\n");@\n");
printf("@exit:
安全退出该文件系统,保存信息.@\n");
printf("@mkdirdirname:
创建子目录.@\n");
printf("@rmdirdirname:
删除子目录.@\n");
printf("@lsdirname:
显示当前目录下信息.@\n");
printf("@cddirname:
更改当前目录.@\n");
printf("@createfilename:
创建一个新文件,并且打开.@\n");
printf("@writefilename:
选择一个打开的文件写入信息@\n");
printf("@readfilename:
选择一个打开的文件读取信息.@\n");
printf("@rmfilename:
删除文件.@\n");
printf("@openfilename:
打开文件.@\n");
printf("@closefilename:
关闭文件.@\n");
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n");
openlist=newOPENLIST;.\n");
format();
printf("初始化已经完成,现在可以进行操作了!
\n\n");
}
while
(1){
cout<cin>>cmd;
if(cmd=="format"){
format();
}
elseif(cmd=="mkdir"){
cin>>command;
mkdir(command);
}
elseif(cmd=="rmdir"){
cin>>command;
rmdir(command);
}
elseif(cmd=="ls"){
listshow();
}
elseif(cmd=="cd"){
cin>>command;
changePath(command);
}
elseif(cmd=="create"){
cin>>command;
create(command);
}
elseif(cmd=="write"){
cin>>command;
write(command);
}
elseif(cmd=="read"){
cin>>command;
read(command);
}
elseif(cmd=="rm"){
cin>>command;
delfile(command);
}
elseif(cmd=="open"){
cin>>command;
open(command);
}
elseif(cmd=="close"){
cin>>command;
close(command);
}
elseif(cmd=="exit"){
exit();
break;
}
elsecout<<"无效指令,请重新输入:
"<}
printf("Thankyouforusingmyfilesystem!
\n");
return1;
}