写入文件不填零 Linux

Write to file without zero fill in Linux

假设我们的目的是创建一个开头有一个大洞的文件,稍后我们将在嵌入式设备上写入该文件 运行 Linux。我们打开文件,获取文件描述符并调用 lseek 以查找某个已知位置。之后,当我们想在搜索到的位置写入该文件时,我们在其上调用 write

但是,在第一次写入时,通过查找创建的空洞会被零填充,如果空洞足够大,此操作可能需要一些时间。在我的应用程序中,不需要这个零初始化,因为洞的长度是精确的,我稍后会用我的数据填充它。

有没有办法避免 seek 之后的第一个 write 调用零填充漏洞(即使它涉及修改文件系统驱动程序)?或者,有没有办法在文件开头之前写入文件(附加到文件的前面)?

您是否尝试过使用标志 MAP_UNINITIALIZED

这可能与您的文件系统有关。在 ext2/3/4、reiser、btrfs、xfs 等上,做你描述的应该 而不是 需要很长时间,因为它们支持所谓的 "sparse files" (在底层存储中占用的文件比文件的大小少space,因为零的运行没有物理存储)。

您可以尝试使用 dd 进行实验以确保情况确实如此:

$ dd if=/dev/zero of=whatever bs=1k seek=1073741824 count=1
1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied, 9.1878e-05 s, 11.1 MB/s
$ ls -al whatever
-rw-r--r-- 1 xxxx xxxx 1099511628800 Jan 31 18:04 whatever
$ du -h whatever
16K whatever

在您的文件系统上,这可能会失败。如果是这样,您需要创建一个稀疏文件,确定您是否可以使用不同的文件系统。

However, on the first write the hole created by seeking gets zero-filled and if the hole is large enough, this operation can take some time.

不,不能。它只会将您提供的数据写入 write()。未写入部分中的零实际上并不存在:它们是文件系统的产物。

出于各种原因,对于您的用例,这可能不是一个可行的解决方案,但我可以想象将大文件拆分成序列号块。缺失或零大小的块应该包含零(或其他一些固定值)。选择适合您要保留的 space 的块大小,并在文件大小和块数之间取得良好的折衷。

或者让它更复杂一点,使用可变块大小,将 "virtual" 大小的单个块存储在其他地方。给定足够复杂的编号系统,您甚至可以在不重命名后续块文件的情况下插入新块...

当然,您需要一个额外的访问层来进行去分块,如果这足够的话,或者在您的应用程序代码中,或者在最坏的情况下作为内核驱动程序挂钩到文件处理中。