C++中的虚拟(平面)文件系统
Virtual (flat) file system in C++
本质上,我需要实现一个程序,作为一个用户空间文件系统,它可以实现非常简单的操作,例如查看磁盘上的内容,将文件从本机文件系统复制到我的文件系统(包含在一个名为"disk01"的文件中),以及从文件系统中删除文件。
我基本上是在寻找一个跳板或一些关于我可以从哪里开始的提示,因为我不确定如何创建自己的"磁盘"并将其他文件放入其中,这是一项家庭作业。
只是一个正在寻找方向的C++学生。
编辑:
我知道这个概念已经在几个不同的地方被用作"VFS"或虚拟文件系统,有点像zip文件(你只能通过一个可以处理zip文件的程序来查看内容)。我基本上是在尝试写我自己的程序,类似于zip或winrar或其他什么,但不是那么复杂和功能丰富。
感谢您迄今为止的建议!你们都是一个巨大的帮助
创建类似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个数据块。
打开一个文件进行非破坏性读/写。对于fstream,这可能是fstream stream(filename)
。
然后使用seek函数在它周围移动。如果你使用的是C++流,这就是stream.seekg(position)
。
然后你会想要二进制读写函数,所以你会使用stream.read(buffer, len)
和stream.write(buffer, len)
。
启动文件系统的一个简单方法是决定块大小。在过去,大多数人使用512字节。你可以这样做,也可以使用4K或使其完全可调。然后在靠近开始的地方留出一个块作为自由空间贴图。这可以是每个块一位,也可以是如果你是懒惰的,每个块一个字节。然后你就有了一个根目录。FAT的方法很简单:它只是一个名称列表,一些元数据,如时间戳、文件大小和块偏移量。我认为FAT块有一个指向文件中下一个块的指针,这样它就可以对文件进行分段,而无需在写入时运行碎片整理。
然后搜索目录,找到文件,转到偏移量并读取块。
真正的文件系统变得复杂的地方是艰巨的任务,比如为文件分配块,这样它们就有了在不浪费空间的情况下在最后增长的空间。处理碎片。在多个线程或程序同时写入时具有良好的性能。在出现意外磁盘错误或电源丢失时进行稳健的恢复。
- 文件系统:复制功能的速度秘诀是什么
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 如何传递多个 std::文件系统选项?
- 遍历顺序由 std::文件系统directory_iterator给出
- libstdc++ 文件系统中未初始化的用法?
- boost::文件系统::recursive_directory_iterator多线程安全
- C++17 文件系统::remove_all 带有通配符路径
- 实验性文件系统库不完整C++?
- 使用文件系统时仍然需要链接到带有 C++20 的 stdc++fs?
- 无法链接文件系统库C++
- 无法识别 Mac c++ 文件系统库
- 使用Boost文件系统C++将具有特定扩展名的文件的名称保存在特定文件夹中
- 获取 clang++:错误:在编译文件系统库的代码时
- C++17 文件系统在 Windows 10 上使用 nuwen MinGW
- C++ VS 错误:<实验/文件系统>提供 std::experimental::文件系统的标头已被Microsoft弃用,将被删除
- 如何修复 MinGW 文件系统探针?
- 将 boost::文件系统::p ath 转换为 char?
- 我可以在 ndk 中使用带有 libc++ 的实验性文件系统吗?
- 是否可以使用 std::文件系统获取根名称列表?
- C++中的虚拟(平面)文件系统