5

本质上,我需要实现一个程序来充当用户空间文件系统,它实现非常简单的操作,例如查看磁盘上的内容,将文件复制到本机文件系统和从本机文件系统复制到我的文件系统(包含在单个文件中)称为“disk01”)并从我的文件系统中删除文件。

我基本上是在寻找一个跳板或一些关于我可以从哪里开始的提示,因为我不确定如何创建自己的“磁盘”并将其他文件放入其中,这是一项家庭作业。

只是一个正在寻找方向的 C++ 学生。

编辑:

我知道这是一个已经在多个不同地方用作“VFS”或虚拟文件系统的概念,有点像 zip 文件(您只能通过可以处理 zip 文件的程序查看内容)。我基本上是在尝试编写自己的程序,类似于 zip 或 winrar 或其他程序,但没有那么复杂和功能丰富。

感谢您迄今为止的建议!你们都是一个巨大的帮助!

4

2 回答 2

9

创建类似 FAT 的磁盘结构非常简单。

在文件中的固定位置,很可能首先,您有一个包含有关磁盘的一些信息的结构。然后是“FAT”,一个简单结构的表格,详细说明了磁盘上的文件。这基本上是一个固定大小的结构表,类似于:

struct FATEntry
{
    char      name[20];  /* Name of file */
    uint32_t  pos;       /* Position of file on disk (sector, block, something else) */
    uint32_t  size;      /* Size in bytes of file */
    uint32_t  mtime;     /* Time of last modification */
};

在此表之后,您有一个固定大小的区域,用于磁盘上的空闲块位图。如果文件系统可以动态增长或收缩,则可能不需要位图。然后是实际的文件数据。

对于这样的系统,所有文件都必须连续布局在磁盘上。当您添加、删除和调整文件大小时,这将导致碎片化。


另一种方法是使用链表方法,例如在旧的 Amiga 文件系统上使用。使用这种方案,所有块都是简单的链表。

就像之前你需要一个实际磁盘数据的结构,可能还有一个显示空闲/分配磁盘块的位图。磁盘数据结构中唯一需要的字段是指向第一个文件的“指针”。

指针我的意思是一个整数,指出一个块在磁盘上的位置。

文件本身可以类似于上面的类 FAT 系统:

struct FileNode
{
    char     name[12];  /* Name of file */
    uint32_t next;      /* Next file, zero for last file */
    uint32_t prev;      /* Previous file, zero for first file */
    uint32_t data;      /* Link to first data block */
    uint32_t mtime;     /* Last modification time */
    uint32_t size;      /* Size in bytes of the file */
};

数据块本身就是链表:

struct DataNode
{
    uint32_t next;  /* Next data block for file, zero for last block */
    char data[BLOCK_SIZE - 4];  /* Actual data, -4 for the block link */
};

链表文件系统的好处是它永远不会碎片化。缺点是您可能必须跳过整个磁盘来获取数据块,并且数据块不能完全使用,因为它们至少需要一个链接到下一个数据块。


第三种方式,在类 Unix 系统中很常见,是让文件数据包含一组指向数据块的链接。这样数据块就不必连续存储在磁盘上。它将包括一些与链表方法相同的缺点,因为块可以存储在整个磁盘上,并且文件的最大大小受到限制。一个优点是可以充分利用数据块。

这样的结构可能看起来像

struct FileNode
{
    char name[16];      /* Name of file */
    uint32_t size;      /* Size in bytes of file */
    uint32_t mtime;     /* Last modification time of file */
    uint32_t data[26];  /* Array of data-blocks */
};

上述结构将最大文件大小限制为 26 个数据块。

于 2012-11-21T06:56:27.823 回答
2

打开文件进行非破坏性读/写。使用 fstream 这可能是fstream stream(filename).

然后使用搜索功能在它周围移动。如果您使用的是 C++ fstream,则为stream.seekg(position).

然后你会想要二进制读写函数,所以你会使用stream.read(buffer, len)and stream.write(buffer, len)

启动文件系统的一种简单方法是确定块大小。过去大多数人使用 512 字节。您可以这样做或使用 4K 或使其完全可调。然后,您在开始附近留出一个块用于自由空间地图。这可以是每个块一个位,或者如果你是懒惰的,每个块一个字节。然后你有一个根目录。FAT 以一种简单的方式做到了这一点:它只是一个名称列表、一些元数据,如时间戳、文件大小和块偏移量。我认为 FAT 块有一个指向文件中下一个块的指针,因此它可以对文件进行分段,而无需在写入时运行碎片整理。

然后你搜索目录,找到文件,转到偏移量并读取块。

真正的文件系统变得复杂的地方在于诸如为文件分配块这样的艰巨任务,以便它们在末端有增长空间而不会浪费空间。处理碎片。在多个线程或程序同时编写时具有良好的性能。面对意外的磁盘错误或断电时的强大恢复。

于 2012-11-21T07:41:57.847 回答