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 硬件)
请谨慎选择错误的设备格式。如有疑问,请仅通过 QEMU 运行以下命令。
lsblk
命令可用于查看有关可从 Zircon 访问的设备的更多信息。
在 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
来查找磁盘条目。我们希望修改第 0 个分区的类型。在这里,我们使用关键字“fuchsia-data”来设置类型 GUID,但如果要使用任意 GUID,则需要在使用“fuchsia-data”的地方提供它。> 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 和 Direct io set 进行调用。
- 重命名:目标文件不存在。如果重命名操作的目标是有效文件,则重命名可以删除文件。这个假设使数学变得简单。
- “写入”操作将单个数据块写入到 vnode 中之前未访问的部分。
- “覆盖”操作将单个数据块写入到之前从较早的“写入”操作分配的块的一部分。
列的键。
- OPERATION:文件系统的客户端请求的操作。
- 块类型:每个文件系统操作都会访问一种或多种类型的块。
- 数据:包含用户数据和目录条目。
- Indirect:文件块映射树中的间接块
- Dindirect:文件块映射树中的 Double indirect 块。
- Inode 表:包含一个或多个 inode 的 Inode 表块。
- 节点位图:包含一个位数组,每个位表示 inode 的空闲/使用状态。
- 数据位图:包含一个位数组,每个位表示数据块的空闲/使用状态。
- Superblock:包含描述文件系统布局和状态的数据。
- IO 类型: IO 访问的类型(读/写)。
- JOURNALED:是否记录 IO 日志。读取不记录日志,但部分写入记录为日志。
- 有条件地访问:根据 OPERATION 的输入参数和文件系统的状态,有条件地访问某些块。
- 否:始终执行 IO。
- 是:文件系统状态和输入参数决定了是否需要此 IO。
- 读取计数:读取的文件系统块数。
- WRITE COUNT(IGNORING JOURNAL):写入的文件系统块数。写入日志或日志的开销不会计入此数值。
- WRITE COUNT (WITH JOURNAL):写入日志,然后写入最终位置的文件系统块数。这不包括用于维护日志状态的块日志写入。
<operation> 行总计(例如“Create Total”)提供了读取/写入的块总数。对于涉及日记的操作,日记功能会为每个操作再写入两个块,即日记条目标头和提交块。
启动(mount/fsck) 文件系统时,Superblock、Inode 表、Inode 位图、数据位图和部分日志会缓存在内存中。因此,系统绝不会针对这些块类型发出读取 IO
运营 | 屏蔽类型 | 广告订单类型 | 已上报 | 有条件访问 | 读取计数 | 写入计数(忽略新闻) | 写入 COUNT(带简报) | 评论 |
---|---|---|---|---|---|---|---|---|
查询/打开 | 数据 | 已读 | 否 | 否 | 大于等于 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 | ||
节点表 | 写入 | 是 | 否 | 0 | 1 | 2 | 新文件的 Inode。 | |
节点位图 | 写入 | 是 | 否 | 0 | 1 | 2 | 将 inode 标记为已分配。 | |
数据位图 | 写入 | 是 | 否 | 0 | 大于等于 0 | 大于等于 0 | 目录可能会增大,以包含新的目录条目。 | |
超级方块 | 写入 | 是 | 否 | 0 | 1 | 2 | 此外,已分配的索引节点编号也会发生变化。 | |
创建总计 | 大于等于 1 | >=4 | 大于等于 10 | 包含用于日志条目的 2 个块。 | ||||
重命名 | 数据 | 已读 | 否 | 否 | 大于等于 1 | 0 | 0 | 重命名涉及在源目录中查找。 |
间接 | 已读 | 否 | 是 | 大于等于 0 | 0 | 0 | ||
DIndirect | 已读 | 否 | 是 | 大于等于 0 | 0 | 0 | ||
数据 | 写入 | 是 | 否 | 0 | 大于等于 1 | 大于等于 2 | 源目录条目。 | |
间接 | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
DIndirect | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
节点表 | 写入 | 是 | 否 | 0 | 1 | 2 | 更新源目录 inode。 | |
数据 | 已读 | 否 | 否 | 大于等于 0 | 0 | 0 | 重命名涉及在源目录中查找。 | |
间接 | 已读 | 否 | 是 | 大于等于 0 | 0 | 0 | ||
DIndirect | 已读 | 否 | 是 | 大于等于 0 | 0 | 0 | ||
数据 | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | 正在写入目标目录条目。 | |
间接 | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
DIndirect | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
节点表 | 写入 | 是 | 是 | 0 | 1 | 2 | 更新目标目录 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) indirect 块。导致读取、修改和写入。 |
DIndirect | 已读 | 否 | 是 | 大于等于 0 | 0 | 0 | ||
数据 | 写入 | 否 | 否 | 0 | 1 | 1 | ||
间接 | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
DIndirect | 写入 | 是 | 是 | 0 | 大于等于 0 | 大于等于 0 | ||
节点表 | 写入 | 是 | 否 | 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 | ||
节点表 | 写入 | 是 | 否 | 0 | 1 | 2 | ||
数据位图 | 写入 | 是 | 否 | 0 | 1 | 2 | 写入新的分配。 | |
数据位图 | 写入 | 是 | 否 | 0 | 大于等于 0 | 大于等于 0 | 释放旧方块。该块位可能属于“分配的块位图”。 | |
超级方块 | 写入 | 是 | 否 | 0 | 1 | 2 | ||
覆盖总计 | 大于等于 0 | >=4 | >=9 | 包含用于日志条目的 2 个块。 |