文件管理实验报告

昆明理工大学信息工程与自动化学院学生实验报告

20## —20## 学年  学期

    课程名称:操作系统       开课实验室:信自楼444          20## 年5 月28日

一、实验目的

用C或C++语言编写和调试一个简单的文件系统,模拟文件管理的基本功能。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。

二、实验原理及基本技术路线图(方框原理图)

用C模拟实现文件系统的管理;要求设计一个多级目录结构的文件系统,能正确描述文件控制块,采用合理的外存分配方式,能实现基本的目录及文件的操作,包括创建、删除、重命名、复制、移动等功能,并对文件有一定的存取权限控制。

请加上程序功能结构图、流程图、数据结构定义、主要变量的说明、函数的说明等

流程图:

文件管理实验报告

主要数据结构

界面采用VC6 MFC环境开发

#define MAXFILE 20   //每个用户最多保存20个文件

#define MAXUSER 10   //假想文件系统最多支持的人数

#define BLOCKSIZE 32 //虚拟磁盘中物理块为每块32字节

#define DISKSIZE BLOCKSIZE*1000  //虚拟磁盘容量为1000*32=32K

struct UFD  //说明文件项的结构数组

{

            char FileName[15];

            char Time[16];      //文件建立或修改时间  如2003/5/6 12:00

            bool IsExist;      //文件是否存在,删除时标为0

            bool IsShared;      //共享标记,共享文件可被其它用户所访问

            bool AttrRead;      //文件是否可读

            bool AttrWrite;     //文件是否可写

            bool AttrExecute;   //文件是否可执行

            HTREEITEM treeNode; //用于树控件显示的结点句柄

            USHORT FileLen;     //文件占用字节数

            USHORT BlockNum;   //文件占用的物理块数

            USHORT FileLink[100];//文件物理块地址数组,每块32字节,限定一个文件最大100*32=3200字节

};

struct MFD

{

            char UserName[10];  //主目录用户名

            bool IsExist;      //该用户否存在

            UFD ufd[MAXFILE];   //用户文件数组 

            USHORT nItem;//UFD个数

};

struct HEADBLOCK

{

            BYTE pStack;    //堆栈指针

            SHORT pBlock[10]; //块号   pBlock[10]是下一个盘块号逻辑地址

};

struct BLOCK          //虚拟磁盘的物理块数据结构

{

   union{

               BYTE block[32];        //一块为32字节

               HEADBLOCK HeadInfo;

            };

};

struct FAT

{

            BLOCK  SuperBlock;     //超级块,指示第一个空闲块逻辑号

            USHORT MaxOpen;       //该用户同时可打开的最大文件数

            USHORT UserNum;       //最户数

            MFD    Mfd[MAXUSER];  //最多可支持10个用户

};

//空闲块成组链接法

bool OpenList[MAXUSER][MAXFILE]; //描述文件是否打开的布尔型数组

FAT FileFAT;            //描述文件记录项的FAT结构

CFile FATIO;                      //负责和VDISK.DAT打交道的文件句柄

CString CurrentUser;              //当前登录的用户名

Int     CurrentID;                //前前登录的用户标识号

说明:本实验采用模拟文件结构的方法,把记录用户帐号,用户文件和磁盘块的信息用当前目录下的VDISK.DAT来记录,可以把VDISK.DAT看成是一个虚拟的磁盘,其头部是FAT结构,用来记录各个用户和文件信息,紧接着是空闲块成组链接法的数据结构,每块32字节,每组10块,共1000块,也就是说,用户文件数据的总容量是32*1000字节,如果程序当前目录下找不到用于做实验用的VDISK.DAT,在登录时程序会提示是否“格式化虚拟磁盘”也就是新建一个VDISK.DAT文件,接着,程序会显示“用户管理”的窗口,此时应新建几个帐号用于登录做实验。

登录后,程序会显示该用户的所有文件,右方的文件列表会显示每个文件的属性信息,和WINDOWS的“资源管理器”相似。用鼠标双击列表的每个文件就可以查看文件的内容。单击“新建文件”按钮可以创建一个新的用户文件。

选中某个文件后,就可以进行相应的操作,如“修改文件”、“删除文件”或是“打开文件”,删除某个文件时检查该文件的属性,如果是只读的,就是显示警告窗口让用户确认是否一定要删除。

硬盘工具可以用图形方式显示“磁盘”块的详细情况,空白块说明该块没有使用,暗红色的说明块已分配,窗口还统计占用的空间大小、用户数等信息。

程序中用到的结构图如下图所示:

文件管理实验报告

文件管理实验报告

三、所用仪器、材料(设备名称、型号、规格等)。

计算机一台

四、实验方法、步骤

void CDlgUser::OnAddUser()

{

    UpdateData(true);

if (FileFAT.UserNum>=10)

{

AfxMessageBox("用户数量已达到最大10个,你可以删除一些无用的帐号!");

return;

}

     for(int i=0;i<10;i++)

{

if(FileFAT.Mfd[i].IsExist==false)

{

              wsprintf(FileFAT.Mfd[i].UserName,m_UserName);

              FileFAT.Mfd[i].IsExist=true;

              FileFAT.Mfd[i].nItem=0;

              break;

}

}

FileFAT.UserNum++;

      WriteFAT();

ReadFAT();

ShowUser();//显示现有的用户列表

m_UserName.Empty();

UpdateData(false);

}

bool ReadBlock(int id, BLOCK* buffer)  //读指定块号内容(32字节)到buffer所指向的单元

{

if(!FATIO) return false;  //如果虚拟磁盘文件句柄为空,出错返回

if(!FATIO.Seek(sizeof(FAT)+(id-1)*BLOCKSIZE,CFile::begin)) return false;//移动文件指针到指定块号

if(FATIO.Read(buffer,BLOCKSIZE)!=BLOCKSIZE) return false;//读该块的内容到buffer指定的单元

return true;

}

bool WriteBlock(int id, BLOCK* buffer)  //把buffer所指向的单元的内容(32字节)写到指定的物理块中

{

    if(!FATIO) return false;  

if(!FATIO.Seek(sizeof(FAT)+(id-1)*BLOCKSIZE,CFile::begin)) return false;

    FATIO.Write(buffer,BLOCKSIZE);

    return true;

}

USHORT AllocBlock()    //分配一物理块,成功返回逻辑块号,失败返回0;

{

     if(!FileFAT.SuperBlock.HeadInfo.pBlock[FileFAT.SuperBlock.HeadInfo.pStack]) return 0; 

//没有空间可分配,失败返回

 if(FileFAT.SuperBlock.HeadInfo.pStack<9)//如果一组的空闲块没有分配完

 {

WriteFAT();

//将返回超级块所指的空闲块,再将堆栈指针加一

return FileFAT.SuperBlock.HeadInfo.pBlock[FileFAT.SuperBlock.HeadInfo.pStack++];

}

else  //如果分配的空闲块是组头

{

         WriteFAT();

USHORT returnBlock=FileFAT.SuperBlock.HeadInfo.pBlock[9];

//将要分配的组头复制到超级块,再返回组头作为空闲块

 if(!ReadBlock(returnBlock,&FileFAT.SuperBlock)) return 0;

return  returnBlock;

 }

    WriteFAT();

 return 0;

}

bool FreeBlock(USHORT BlockID)  //回收一物理块,成功返回TRUE,失败返回FALSE

{

    if(FileFAT.SuperBlock.HeadInfo.pStack>0)//如果该组的空闲没有回收满

{

           //堆栈指针退一,把回收的块号记入超级块

FileFAT.SuperBlock.HeadInfo.pBlock[--FileFAT.SuperBlock.HeadInfo.pStack]=BlockID;

   BLOCK newBlock;

 //把回收的块内容清空

  if (!WriteBlock(BlockID,&newBlock)) return false;

}

else//如果该组已回收满,需要加入一新组的话

{

       if (!WriteBlock(BlockID,&FileFAT.SuperBlock)) return false;//将超级块的栈内容复制到要回收的块中

                   FileFAT.SuperBlock.HeadInfo.pStack=9;//将超级块的栈指针指向回收的块

                   FileFAT.SuperBlock.HeadInfo.pBlock[9]=BlockID;

}

WriteFAT();

return true; 

}

bool ReadFAT()  //从虚拟磁盘中读取FAT结构信息到FileFAT中

{

ZeroMemory(&FileFAT,sizeof(FileFAT));

 FATIO.SeekToBegin();

    if (!FATIO.Read(&FileFAT,sizeof(FileFAT))) return false;

return true;

}

bool Format()   //格式化虚拟磁盘,创建VDISK.DAT,所有用户和文件信息将被清空!

{

    CString FATFile;

 int i;

 char fname[128];

GetCurrentDirectory(128,fname);   //FAT表信息保存在当前目录的VDISK.DAT中

FATFile.Format("%s",fname);

 if (FATFile.Right(1)!="\\")

FATFile+="\\VDISK.DAT";

 else

         FATFile+="VDISK.DAT";

 CFile fout;

 if( !fout.Open(FATFile,CFile::modeCreate|CFile::modeWrite,NULL))

return false;

 ZeroMemory(&FileFAT,sizeof(FileFAT));

 FileFAT.SuperBlock.HeadInfo.pStack=0;

 for(i=0;i<10;i++)

 {

        FileFAT.SuperBlock.HeadInfo.pBlock[i]=i+1;

 }

 fout.WriteHuge(&FileFAT,sizeof(FileFAT));

 BYTE *Buffer;

 Buffer=(BYTE*)malloc(DISKSIZE);//申请成组链接法所需的磁盘块空间

    ZeroMemory(Buffer,DISKSIZE);

 BLOCK newBlock;

for (i=10;i<=990;i+=10)

 {

  ZeroMemory(&newBlock,sizeof(newBlock));

 newBlock.HeadInfo.pStack=0;

 for (int k=0;k<10;k++)

newBlock.HeadInfo.pBlock[k]=i-9+k;

  memcpy(Buffer+32*(i-1),&newBlock,32);

 }

fout.WriteHuge(Buffer,DISKSIZE); //将格式化的块信息写入VDISK.DAT

 free(Buffer);

  fout.Close();

 AfxMessageBox("创建虚拟磁盘文件成功!请选择用户管理添加新用户。");

 return true;

}

//StartIO()用于完成与虚拟磁盘的IO的初始化工作

void StartIO() //打开VDISK.DAT文件,把该文件句柄保存在全局变量中,如果该文件不存在,创建并初始化该文件。

{

     CString FATFile;

 char fname[128];

GetCurrentDirectory(128,fname);   //FAT表信息保存在当前目录的VDISK.DAT中

 FATFile.Format("%s",fname);

 if (FATFile.Right(1)!="\\")

 FATFile+="\\VDISK.DAT";

 else

         FATFile+="VDISK.DAT";

 bFormated=true;

 if (!FileExist(FATFile))

{

 AfxMessageBox("当前目录下找不到VDISK.DAT,该文件是用来模拟磁盘及文件管理表。\n单击确定创建新的虚拟磁盘文件!");

 bFormated=false;

 if (!Format())

 {

 AfxMessageBox("创建文件系统出错!");

 return;

 }

 }

 if(!FATIO.Open(FATFile,CFile::modeReadWrite|CFile::shareDenyWrite,NULL))

 {

            AfxMessageBox("调入FAT表失败,文件系统可能出错!");

  bFormated=false;

  return;

 }

}

bool CreateNewFile(CString FileName, CString FileContent, bool AttrRead, bool AttrWrite, bool AttrExecute, bool AttrShare)  //创建一个新文件

{

    if (FileNameExist(FileName)) return false;  //如果要建立的文件与现有文件重名,失败返回

int i,FilePos,FileLen,BlockNum,BlockID;

bool flag=false;

FileContent.TrimLeft();FileContent.TrimRight();

FileLen=FileContent.GetLength();

char Content[32];//把文件内容分割成每个物理块大小后送content字符数组,以备写入磁盘块中

for(i=0;i

{

 if(!FileFAT.Mfd[CurrentID].ufd[i].IsExist)//扫描所有文件项,如果标记不存在就准备写入新建文件信息

      {

 flag=true;FilePos=i;

        break;

   }

}

    if(!flag) return false;

BlockNum=(int)FileLen/BLOCKSIZE+1;//计算文件占用的块数

  for(i=0;i

{

BlockID=AllocBlock();//得到分配的块的逻辑号

       if(BlockID)

   {

 FileFAT.Mfd[CurrentID].ufd[FilePos].FileLink[i]=BlockID;//逐个将块号记入文件项中

wsprintf(Content,FileContent.Mid(i*32,32));//写入一个块的内容到缓冲区

if(!WriteBlock(BlockID,(BLOCK*)Content)) return false;//从缓冲区写到虚拟磁盘

    }

else

{

return false;

}

}

//以下是填写文件的属性,时间等信息

wsprintf(FileFAT.Mfd[CurrentID].ufd[FilePos].FileName,FileName.Left(15));

    FileFAT.Mfd[CurrentID].ufd[FilePos].IsExist=true;

FileFAT.Mfd[CurrentID].ufd[FilePos].BlockNum=BlockNum;

FileFAT.Mfd[CurrentID].ufd[FilePos].AttrExecute=AttrExecute;

    FileFAT.Mfd[CurrentID].ufd[FilePos].AttrRead=AttrRead;

FileFAT.Mfd[CurrentID].ufd[FilePos].AttrWrite=AttrWrite;

FileFAT.Mfd[CurrentID].ufd[FilePos].IsShared=AttrShare;

    FileFAT.Mfd[CurrentID].ufd[FilePos].FileLen=FileContent.GetLength();

wsprintf(FileFAT.Mfd[CurrentID].ufd[FilePos].Time,GetCurrentTime());

FileFAT.Mfd[CurrentID].nItem++;

WriteFAT();

ShowUserFiles();//刷新用户文件列表,以便将新建的文件显示出来

return true;

}

CString ReadFile(CString FileName)  //给定当前用户的文件名,将文件内容以Cstring字符串返回

{

    int i,FilePos;

bool flag=false;

char Buffer[32];

CString strReturn;

for(i=0;i

{

if(FileFAT.Mfd[CurrentID].ufd[i].FileName==FileName&&FileFAT.Mfd[CurrentID].ufd[i].IsExist==true)

{

flag=true;FilePos=i;break;

}

}

if(!flag) return "";

for(i=0;i

{

ZeroMemory(Buffer,32);

if(!ReadBlock(FileFAT.Mfd[CurrentID].ufd[FilePos].FileLink[i],(BLOCK*)Buffer)) return "";

strReturn+=Buffer;

}

return strReturn;

}

bool KillFile(CString FileName)//根据文件名删除用户当前文件

{

    int i,FilePos;

bool flag=false;

for(i=0;i

{

if(FileFAT.Mfd[CurrentID].ufd[i].FileName==FileName&&FileFAT.Mfd[CurrentID].ufd[i].IsExist==true)

{

                flag=true;  FilePos=i;      break;

}

}

if(!flag) return false;

for(i=0;i

if(!FreeBlock(FileFAT.Mfd[CurrentID].ufd[FilePos].FileLink[i])) return false;

FileFAT.Mfd[CurrentID].nItem--;

     ZeroMemory(&FileFAT.Mfd[CurrentID].ufd[FilePos],sizeof(UFD));

     WriteFAT();

    return true;

}

bool ModifyFile(CString FileName, CString FileContent, bool AttrRead, bool AttrWrite, bool AttrExecute, bool AttrShare)     //修改文件,包括文件名、属性和内容

{

    int i,FilePos,BlockNum,BlockID;

    bool flag=false;

FileContent.TrimLeft();

FileContent.TrimRight();

char Content[32];

for(i=0;i

{

if(FileFAT.Mfd[CurrentID].ufd[i].FileName==SelectedFileName)

{

flag=true; FilePos=i;break;

}

}

    if(!flag) return false;

for(i=0;i

{

if(!FreeBlock(FileFAT.Mfd[CurrentID].ufd[FilePos].FileLink[i])) return false;

}

      ZeroMemory(&FileFAT.Mfd[CurrentID].ufd[FilePos].BlockNum,200);

BlockNum=(int)FileContent.GetLength()/BLOCKSIZE+1;

      for(i=0;i

{

BlockID=AllocBlock();

         if(BlockID)

{

                FileFAT.Mfd[CurrentID].ufd[FilePos].FileLink[i]=BlockID;

            wsprintf(Content,FileContent.Mid(i*32,32));

                if(!WriteBlock(BlockID,(BLOCK*)Content)) return false;

}

else

{

                return false;

}

}

wsprintf(FileFAT.Mfd[CurrentID].ufd[FilePos].FileName,FileName.Left(15));

       FileFAT.Mfd[CurrentID].ufd[FilePos].IsExist=true;

FileFAT.Mfd[CurrentID].ufd[FilePos].BlockNum=BlockNum;

FileFAT.Mfd[CurrentID].ufd[FilePos].AttrExecute=AttrExecute;

       FileFAT.Mfd[CurrentID].ufd[FilePos].AttrRead=AttrRead;

FileFAT.Mfd[CurrentID].ufd[FilePos].AttrWrite=AttrWrite;

FileFAT.Mfd[CurrentID].ufd[FilePos].IsShared=AttrShare;

    FileFAT.Mfd[CurrentID].ufd[FilePos].FileLen=FileContent.GetLength();

wsprintf(FileFAT.Mfd[CurrentID].ufd[FilePos].Time,GetCurrentTime());

WriteFAT();

ShowUserFiles();

return true;

}

void CDlgDisk::CalcBlock()// “磁盘工具”中的计算并显示磁盘块使用情况功能

{

     BYTE DiskImage[32000];//磁盘数据区所有物理块映像数组

 FATIO.Seek(sizeof(FileFAT),CFile::begin);//跳过FAT结构,定位文件指针至数据区物理块头

 FATIO.Read(&DiskImage,32000);//读物理块映像

register sum=0;//保存使用的总块数

for(int i=0;i

 {

       m_ctrlChecker.SetBlock(FileFAT.SuperBlock.HeadInfo.pBlock[i]-1, RGB(200, 0, 0));

 sum++;

 }

 BLOCK testBlock;

 memcpy(&testBlock,&DiskImage[FileFAT.SuperBlock.HeadInfo.pBlock[9]*32],BLOCKSIZE);

    while(testBlock.HeadInfo.pBlock[9]>0)

 {

          for(i=0;i<10;i++)

 {

             m_ctrlChecker.SetBlock(testBlock.HeadInfo.pBlock[i]-1, RGB(200,0,0));

             sum++;

 }

  memcpy(&testBlock,&DiskImage[testBlock.HeadInfo.pBlock[9]*32],BLOCKSIZE);

 }

 AddPiece(RGB(200,0,0),(int)sum*360/100,"Used");  

 m_Used.Format("已用空间:%d 字节",sum*32);

m_UserNum.Format("用户数:%d",FileFAT.UserNum);

 UpdateData(false);

}

五、实验过程原始记录(数据、图表、计算等)

六、实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸)

    

由于期末考试临近,复习压力巨大,最后一次实验不能有足够的时间上机操作。但是通过对网上的这个代码反复研究后,也看懂了很多,对一个多级目录结构的文件系统,看懂了别人是如何描述文件控制块,采用合理的外存分配方式,实现了基本的目录及文件的操作,包括创建、删除、重命名、复制、移动等功能,并对文件有一定的存取权限控制。通过此次实验,我对文件系统、文件目录、目录结构有了更深一步的理解,对整个操作系统的学习有了很大的帮助。

相关推荐