1

我的目标是立即为文件分配大量空间,而不会生成稀疏文件。从文件中读取应该输出剩余空间中的垃圾,而不是 0。

两者都truncate制作fallocate稀疏文件。

这可能吗?

4

1 回答 1

1

我们能避免零吗?

不,这是不可能的。

出于明显的安全原因,内核将清除在删除、截断等时释放的扇区。因此,当您分配新文件时,它会自动全为零。该清除可能是虚拟的(与在磁盘上物理写入零相反,特别是因为它不适用于 SSD - 详情请参阅shred(1))。

如果您想要非常快速的分配,唯一的方法是创建自己的分区并自己管理它。如果您目前依赖 ext4 或其他类似文件系统的许多功能,这不是一件容易的事。

由于扇区应该已经设置为零,因此在磁盘上分配新(大)文件时不应该对速度产生任何影响。

稀疏文件

根据经验,当您将零写入文件时,它会将零物理写入磁盘。它根本不会创建稀疏文件。

在软件中,创建稀疏文件需要您使用truncate()/ftruncate()函数来放大文件并lseek()在下一个write(). 但是,如果您执行write()全零操作,则操作系统不会尝试将它们转换为稀疏文件。

换句话说,你可以用 C++ 写这样的东西,你不会得到一个稀疏文件:

int fd = open(filename, O_CREAT | O_WRONLY, 0600);
std::vector<uint8_t> buffer(size);
write(fd, buffer.data(), buffer.size());
close(fd);

此代码示例假定一个相对较小的size参数。否则使用循环会更有效率,而且不太可能破坏你的记忆。

在您的控制台中,这意味着使用将每个字节写入目标文件的工具。对于非常大的文件(即写入 1Tb ......你知道......)它会很慢这是一个这样的工作方式:

head -c${SIZE} /dev/zero >"${OUTPUT}"

请注意,某些工具有意支持稀疏文件。例如:

  • cp可用于复制稀疏文件。
  • dd将完成在输入文件中查找零的工作,并在truncate()不写入零的情况下适当地增加输出。
  • 等等。

在磁盘上分配物理文件当然有很好的理由,即使该操作很慢:

  • 您正在创建一个数据库文件;在这种情况下使用稀疏文件会非常危险(即写入可能在错误的时间失败)并且分配新的 inode 很,因此您的数据库吞吐量可能会受到影响(尽管这只发生在写入和增长您的数据库文件时类似于在必要时为您的文件分配一个 inode)。
  • 您正在创建一个虚拟磁盘;我用稀疏文件测试了那些,这太可怕了;至少在我的带硬盘的旧电脑上,运行 VPS 时速度太慢了
  • 您正在创建一个交换文件;使用稀疏文件进行交换确实不是一个好主意(这就像故意找麻烦!在分配新块的缓慢,文件可能会碎片化的事实,磁盘的可能性之间)在您需要该交换空间时已满...)
于 2019-10-06T23:29:57.337 回答