最低 FS

MinFS 是为 Zircon 构建的类似于 unix 的简单文件系统。

它目前支持的文件大小上限为 4 GB。

使用 MinFS

主机设备(仅限 QEMU)

  • 创建存储 MinFS 的磁盘映像

    # (Linux)
    $ truncate --size=16G blk.bin
    # (Mac)
    $ mkfile -n 16g blk.bin
    
  • 使用“--”在您的平台上执行运行 zircon 脚本才能传递 参数直接传递给 QEMU,然后使用“-hda”指向该文件。如果您 要连接其他设备,则可为它们提供“-hdb”、“-hdc” 依此类推。

    fx set bringup.x64
    fx build
    fx qemu -- -hda blk.bin
    

目标设备(QEMU 和 Real Hardware)

注意不要格式化错误的设备。如有疑问,请仅运行 运行此命令 lsblk 命令可用于查看有关设备的更多信息 。

  • 在 Zircon 中,lsblk 可用于列出当前所在的块设备 系统。在下面的示例系统中,/dev/class/block/000 是一个原始值, 块存储设备

    > lsblk
    ID  DEV      DRV      SIZE TYPE           LABEL
    000 block    block     16G
    
  • 我们先向这个块存储设备添加 GPT。

    > gpt init /dev/class/block/000
    ...
    > lsblk
    ID  DEV      DRV      SIZE TYPE           LABEL
    002 block    block     16G
    
  • 现在,我们在此设备上已经有了 GPT,我们看看能用它做些什么。 (注意:对 GPS 进行操作后,设备编号可能会发生变化。使用lsblk 来跟踪如何引用块存储设备)。

    > gpt dump /dev/class/block/002
    blocksize=512 blocks=33554432
    Partition table is valid
    GPT contains usable blocks from 34 to 33554398 (inclusive)
    Total: 0 partitions
    
  • gpt dump 告诉我们一些重要信息:它告诉我们 (1) 区块有多大; (2) 哪些代码块可供我们实际使用。 让我们用 MinFS 文件系统填满磁盘的一部分。

    > gpt add 34 20000000 minfs /dev/class/block/002
    
  • 在 Zircon 中,将分区格式设置为 MinFS。使用 lsblk 时,您应该会看到 块存储设备(即整个磁盘)和稍微小一点的设备(包含整个磁盘), 是分区在上面的输出中,分区为设备 003, 路径为 /dev/class/block/003

    > mkfs <PARTITION_PATH> minfs
    
  • 如果您希望设备在重新启动时自动装载,请使用 GPT 工具设置其类型。正如我们前面所说,您必须lsblk再次使用 找到该磁盘的条目。我们想要修改 。这里我们使用关键字“fuchsia-data”用于设置类型 GUID 如果您想使用任意 GUID,则可以在 “紫红色数据”。

    > gpt edit 0 type fuchsia-data <DEVICE_PATH>
    
  • 以后每次启动时,该分区都将自动装载到 /data

  • 如果您不希望自动装载该分区,则可以 分区的可见性(即 GUID),并直接手动装载分区即可。

    > mount <PARTITION_PATH> /data
    
  • 任何写入 /data(此 GUID 的装载点)的文件都将保留 如需测试这一点,请尝试在新的 MinFS 卷上创建一个文件, 但发现它仍然存在

    > touch /data/foobar
    > dm reboot
    > ls /data
    
  • 确定在每个子目录中装载了哪个块存储设备/文件系统 请使用以下命令:

    > df <PATH>
    

Minfs 操作

以下部分介绍了为完成简单的结束,需要执行哪些 IO 用户操作,如 read()/write()。

假设

  • 不会缓存或批量执行的操作(读取或写入)。上述各项操作 就像使用 Sync 和 Directio Set 一样调用。
  • 如需重命名,请执行以下操作:目标文件不存在。在以下情况下,重命名可能会删除文件: 重命名操作的目标为有效文件。这种假设 让数学变得简单易行。
  • “撰写”操作将单个数据块写入 vnode 的未访问部分。
  • “覆盖”操作会将单个数据块写入数据块中的一部分 之前从之前的“Write”中分配的块,操作。

列的键。

  1. OPERATION:文件系统的客户端请求的操作。
  2. 阻止类型:每个文件系统操作都会导致访问一种或多种类型 一组数据。
    • 数据:包含用户数据和目录条目。
    • 间接:文件块映射树中的间接块
    • Dindirect:文件块映射树中的两个间接块。
    • Inode 表:包含一个或多个 inode 的 Inode 表块。
    • Inode 位图:包含一系列位,每个位表示空闲/已使用状态 多个 inode 的列表。
    • 数据位图:包含位数组,其中每个位都表示空闲/已使用状态 一组数据块
    • 超级块:包含描述文件系统布局和状态的数据。
  3. IO TYPE:IO 访问的类型、读/写类型。
  4. JOURNALED:IO 是否会记入日志。读数不会记入日志,但有一些读数 写入日志的数据。
  5. 条件访问:取决于 OPERATION 的输入参数和 某些块是有条件地访问。
    • 否:始终会执行 IO。
    • 是:文件系统状态和输入参数决定了此 IO 是否 。
  6. READ COUNT:读取的文件系统块数。
  7. WRITE COUNT (IGNORING JOURNAL):写入的文件系统块数。写作 日记或日记开销不会计入此数字。
  8. WRITE COUNT (WITH JOURNAL):写入日志的文件系统块数 然后再到达最终位置这不包括块日志 以保持日志状态。

一个<operation>与“创建总计”一样,“总计”提供屏蔽的总数 读写。对于涉及日记的操作,该日记另外还写了两篇 日志块、日记条目标头和提交块。下方所示的数字 的写入次数总计是 WRITE COUNT (WITH JOURNALING) 的总和 和日志开销,即每个操作 2 个块。

超级块、Inode 表、Inode 位图、数据位图和 Journal 的一部分 在启动(装载/fsck)文件系统时缓存在内存中。读取 IO 是 从未针对这些屏蔽类型签发的警告。

运营 屏蔽类型 广告订单类型 新闻稿 有条件地访问 已读数 写入计数(忽略新闻报道) 写入次数(含新闻稿) 评论
查找/打开 数据 已读 >=1 0 0 如果目录很大,则会读取多个块。
间接 已读 >=0 0 0 可以通过直接屏蔽设置查询。所以“间接”为可选项。
DIndirect 已读 >=0 0 0 可以通过直接屏蔽设置查询。因此 dindirect 是可选的。
查询/打开总计 >=1 0 0
创建 数据 已读 >=1 0 0 创建涉及首先查找名称冲突。
间接 已读 >=0 0 0
DIndirect 已读 >=0 0 0
数据 写入 0 >=1 >=2
间接 写入 0 >=0 >=0
DIndirect 写入 0 >=0 >=0
Inode 表 写入 0 1 2 新文件的 Inode。
Inode 位图 写入 0 1 2 将 inode 标记为已分配。
数据位图 写入 0 >=0 >=0 目录可能会增大,以包含新的目录条目。
超级区块 写入 0 1 2 除此之外,分配的 inode 编号也会发生变化。
创建总计 >=1 >=4 >=10 包含 2 个用于日记条目的块。
重命名 数据 已读 >=1 0 0 重命名操作需要在源目录中查找。
间接 已读 >=0 0 0
DIndirect 已读 >=0 0 0
数据 写入 0 >=1 >=2 源目录条目。
间接 写入 0 >=0 >=0
DIndirect 写入 0 >=0 >=0
Inode 表 写入 0 1 2 更新源目录 inode。
数据 已读 >=0 0 0 重命名操作需要在源目录中查找。
间接 已读 >=0 0 0
DIndirect 已读 >=0 0 0
数据 写入 0 >=0 >=0 正在写入目标目录条目。
间接 写入 0 >=0 >=0
DIndirect 写入 0 >=0 >=0
Inode 表 写入 0 1 2 更新目标目录 inode。
Inode 表 写入 0 1 2 已重命名文件的 mtime。
数据位图 写入 0 >=0 >=0 如果我们分配了数据,则为间接或间接的块。
超级区块 写入 0 1 2
重命名总计 >=1 >=5 >=12 包含 2 个用于日记条目的块。
已读 数据 已读 >=1 0 0
间接 已读 >=0 0 0
DIndirect 已读 >=0 0 0
读取总计 >=1 0 0
写入 间接 已读 >=0 0 0 即使写入未被覆盖,我们也可能与现有数据共享 (D) 间接块。指向读取修改写入。
DIndirect 已读 >=0 0 0
数据 写入 0 1 1
间接 写入 0 >=0 >=0
DIndirect 写入 0 >=0 >=0
Inode 表 写入 0 1 2 Inode 的 mtime 更新。
数据位图 写入 0 1 2 针对已分配的块。
超级区块 写入 0 1 2 分配的块数的变化。
写入总计 >=0 >=4 >=9 包含 2 个用于日记条目的块。
覆盖 数据 已读 >=0 0 0 读取修改写入。
间接 已读 >=0 0 0
DIndirect 已读 >=0 0 0
数据 写入 0 1 1
间接 写入 0 >=0 >=0
DIndirect 写入 0 >=0 >=0
Inode 表 写入 0 1 2
数据位图 写入 0 1 2 写入新分配。
数据位图 写入 0 >=0 >=0 释放旧块。此块位可能属于分配的块位图。
超级区块 写入 0 1 2
覆盖总计 >=0 >=4 >=9 包含 2 个用于日记条目的块。