C++模拟FAT文件系统的设计思路

1. 设计目的

通过实现文件系统的管理,操作虚拟磁盘中的文件存储空间、目录结构及文件操作,帮助理解文件系统的内部数据结构、功能以及实现过程。主要目标是通过实践掌握文件系统的设计与实现。

2. 系统功能要求

  1. 文件存储管理
    在内存中创建一个虚拟磁盘空间作为文件存储分区,模拟文件系统的功能。通过文件系统,用户能够进行文件的创建、删除、读取、写入、目录操作等。退出时,应将虚拟文件系统保存到磁盘上,并在下次启动时恢复。

  2. 文件存储空间分配

    1. 存储空间分配方式

    文件存储空间的分配采用基于数组下标的方式,类似于链式分配,但通过下标查找磁盘块的位置。具体地,文件分配表(FAT)中的每一项记录一个磁盘块的下标,指示该块数据的下一个磁盘块的位置。如果该磁盘块为文件的最后一块,则在FAT表中该项的值为 END,表示文件结束;如果该磁盘块为空,则该项的值为 FREE,表示该磁盘块为空闲状态。

    2. 存储结构与布局
    • 虚拟磁盘:虚拟磁盘被模拟为一个包含多个磁盘块的数组。每个磁盘块大小为 1024 字节,磁盘总大小为 1024000 字节,划分为多个磁盘块。

    • 文件分配表(FAT):FAT表通过一个数组来管理磁盘块的分配情况。每个FAT表项包含一个下标,表示当前磁盘块的下一个簇的位置。

      • FAT项内容:

        • FREE:表示该磁盘块为空闲状态。
        • END:表示该磁盘块为文件的最后一个簇。
        • 其他值:表示当前磁盘块的下一个簇的位置。
    • 磁盘块分配:文件分配时,根据文件大小从FAT表中查找空闲的磁盘块,将文件的数据存储到这些磁盘块中,并通过FAT表项将它们链接起来。

    3. 文件存储空间分配流程
    1. 文件分配
    • 系统会根据文件的大小和可用的空闲磁盘块,分配足够数量的磁盘块。
      • 每个磁盘块通过FAT表项链接,形成一个链表。文件的每个块会指向下一个块,直到文件结束。
      • 在分配磁盘块时,如果找到的磁盘块为 FREE,则将该磁盘块分配给文件。
      • 如果文件块已分配完,最后一个块将指向 END,表示文件的结束。
    1. 文件释放
      • 文件释放时,通过FAT表遍历文件占用的磁盘块,将其对应的FAT项标记为 FREE,表示该磁盘块空闲。
      • 磁盘块的释放通过遍历链表方式完成,直到找到标记为 END 的块,表示文件释放完毕。
    2. 查找空闲块
      • 在磁盘块分配时,系统会查找FAT表中状态为 FREE 的项,找到后分配该磁盘块并更新FAT表。
  3. 目录结构管理
    在这个文件系统中,文件目录之间的关系是通过 目录项(FCB) 来建立的。每个文件(包括文件和目录)都对应一个 FCB,而每个目录(包含文件或子目录)也是一个特殊的文件,其中的每个条目(目录项)表示一个文件或子目录。

    1.2 根目录和子目录的关系

    根目录(/)是整个文件系统的顶级目录,它的作用类似于一个入口点。根目录本身也是一个目录文件,它包含指向其他子目录和文件的目录项。根目录的每个目录项可能是一个 文件,也可能是一个 子目录,从而形成了文件系统的层次结构。

    例如,根目录中的一个目录项可能指向一个子目录 /root/subdir1,而另一个目录项可能指向一个普通文件 /root/file1.txt

    1.3 目录项的查找

    当需要访问某个目录或文件时,文件系统会通过路径逐级查找目录项。例如,在路径 /root/subdir1/file1.txt 中,系统首先查找根目录中的目录项,找到指向 subdir1 的目录项,然后进入 subdir1 子目录,再查找该子目录中指向 file1.txt 的目录项。

    2. 目录和子目录之间的关系

    每个 子目录 本质上也是一个目录,它的结构与根目录类似,只是它位于更深的层次中。子目录的创建和管理也采用类似的方式进行。

    2.1 子目录的创建
    • 每个目录都是一个文件,包含多个目录项。
    • 创建子目录时,系统会在父目录中添加一个新的目录项,该目录项指向子目录的起始磁盘块,同时为该子目录分配一块新的磁盘空间。
    • 子目录也是一个文件,它包含对该子目录下所有文件和子目录的管理。

    例如,创建 /root/subdir1 子目录时,文件系统会在 root 目录下添加一个目录项,指向 subdir1 子目录的起始磁盘块。

    2.2 子目录的查找

    当需要进入某个子目录时,系统会从父目录中查找该子目录的目录项。查找过程是逐级进行的。例如,从根目录进入 /root/subdir1 时,系统会首先在根目录中查找 subdir1 目录项,然后进入该子目录,再查找该子目录中的文件或其他子目录。

    3. 目录结构的层次关系

    3.1 多级目录的实现

    文件系统采用多级目录结构,可以通过路径逐级访问到具体的文件或子目录。每个目录项包含对父目录的引用,因此系统能够在多级目录结构中进行有效的导航。

    例如,/root/subdir1/file1.txt 表示:

    • root 是根目录,subdir1 是根目录下的一个子目录,file1.txtsubdir1 子目录下的一个文件。
    • 系统在根目录中查找 subdir1,进入 subdir1 后,再查找 file1.txt 文件。
    3.2 目录项表(目录的文件)

    每个目录本质上是一个文件,目录文件包含多个目录项。每个目录项表示一个文件或子目录。目录文件本身的 文件长度 表示目录项的数量。

    每个目录文件(包括根目录和子目录)的格式相同,都是由多个目录项(FCB)组成的。系统通过目录项的 起始磁盘块号 来查找目录文件的内容。

    4. 查找目录项的过程

    系统如何查找目录项(文件或子目录)?

    1. 查找根目录:系统首先查找根目录(/)的目录项,获取根目录下的所有文件和子目录。
    2. 逐级查找子目录:当需要进入子目录时,系统从父目录中查找相应的目录项,找到该子目录的起始磁盘块,并进入该子目录。
    3. 查找文件:在子目录中查找文件时,系统会根据文件名和扩展名从该目录的目录项中查找,找到文件所在的磁盘块位置。

    5. 目录操作

    5.1 创建目录 my_mkdir
    • 系统在父目录中分配一个新的目录项,并为该子目录分配磁盘块。
    • 新创建的子目录会被初始化,并包含至少一个目录项(用于存储该子目录的目录项)。
    5.2 删除目录 my_rmdir
    • 删除子目录时,系统会检查该目录是否为空(即该目录项下没有其他文件或子目录)。
    • 如果目录为空,系统会删除目录项,并释放与该目录相关的磁盘块。
    • 如果目录不为空,删除操作会失败,必须先删除子目录中的文件或子目录。
    5.3 改变当前目录 my_cd
    • 当前目录由 currentdir 变量记录,改变当前目录时,系统根据路径更新当前目录。
  4. 提供文件操作命令

    • my_format:格式化虚拟磁盘并创建根目录及管理数据结构。
    • my_mkdir:创建子目录。
    • my_rmdir:删除子目录。
    • my_ls:列出目录中的内容。
    • my_cd:更改当前目录。
    • my_create:创建文件。
    • my_open:打开文件。
    • my_close:关闭文件。
    • my_write:写文件。
    • my_read:读文件。
    • my_rm:删除文件。
    • my_exitsys:退出文件系统。

3. 开发平台

  • 编程语言:C++

4. 数据结构设计

4.1 常量定义
  • BLOCKSIZE = 1024:磁盘块大小。
  • SIZE = 1024000:虚拟磁盘空间总大小。
  • END = 65535:文件结束标志。
  • FREE = 0:磁盘块空闲标志。
  • ROOTBLOCKNUM = 2:根目录区所占盘块总数。
  • MAXOPENFILE = 10:最多同时打开的文件数。
4.2 数据结构
  1. 文件控制块 (FCB)
    记录文件的控制信息,是文件目录项的内容。

    typedef struct FCB {
        char filename[8];   // 文件名
        char exname[3];     // 文件扩展名
        unsigned char attribute; // 文件属性:0 - 目录文件,1 - 数据文件
        unsigned short time; // 文件创建时间
        unsigned short data; // 文件创建日期
        unsigned short first; // 文件起始盘块号
        unsigned long length; // 文件长度(字节数)
        char free;           // 目录项是否为空,0 - 空,1 - 已分配
    } fcb;
    
  2. 文件分配表 (FAT)
    记录磁盘块的分配情况,每个文件占据的磁盘块的块号及块的空闲状态。

    typedef struct FAT {
        unsigned short id; // 盘块号
    } fat;
    
  3. 用户打开文件表 (USEROPEN)
    记录用户打开的文件的相关信息。

    typedef struct USEROPEN {
        char filename[8];   // 文件名
        char exname[3];     // 文件扩展名
        unsigned char attribute; // 文件属性:0 - 目录,1 - 数据文件
        unsigned short time; // 文件创建时间
        unsigned short data; // 文件创建日期
        unsigned short first; // 文件起始盘块号
        unsigned long length; // 文件长度
        char free;           // 目录项是否为空,0 - 空,1 - 已分配
        int dirno;           // 目录项所在盘块号
        int diroff;          // 目录项在盘块中的位置
        char dir[MAXOPENFILE][80]; // 文件所在目录路径
        int count;           // 读写指针的位置
        char fcbstate;       // 文件控制块状态:1 - 修改,0 - 未修改
        char topenfile;      // 打开文件表项是否被占用
    } useropen;
    
  4. 引导块 (BLOCK0)
    存放磁盘的描述信息,包括磁盘块大小、磁盘块数量、文件分配表等。

    typedef struct BLOCK0 {
        char information[200];     // 相关描述信息
        unsigned short root;       // 根目录起始盘块号
        unsigned char *startblock; // 数据区开始位置
    } block0;
    

5. 系统全局变量

  • unsigned char *myvhard: 指向虚拟磁盘的起始地址。
  • useropen openfilelist[MAXOPENFILE]: 用户打开文件表数组。
  • useropen *ptrcurdir: 指向当前目录所在文件表项。
  • char currentdir[80]: 记录当前目录的路径。
  • unsigned char *startp: 数据区的起始位置。

6. 虚拟磁盘空间布局

虚拟磁盘总共被划分为1000个磁盘块,每个磁盘块的大小为1024字节。布局如下:

  • 引导块:占1个磁盘块。
  • 两张FAT表:各占2个磁盘块。
  • 数据区:其余的空间分配给数据区,其中第6个磁盘块被分配为根目录区。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值