假设你有一个带有许多空字节\x00
的文件。这些许多空字节\x00
被称为空洞。存储空字节并不高效,因为我们知道文件中有很多这样的字节,那么为什么要将它们存储在存储设备上呢?相反,我们可以存储描述这些零的元数据。当进程读取文件时,这些零字节块会动态生成,而不是存储在物理存储设备上(请查看维基百科上的此示意图):
这就是稀疏文件高效的原因,因为它不在磁盘上存储零,而是保存足够的数据描述将要生成的零。
注意: 稀疏文件的逻辑文件大小大于物理文件大小。这是因为我们没有将零物理存储在存储设备上。
编辑:
当您运行:
$ dd if=/dev/zero of=output bs=1G count=4
这里的命令将4G字节的空字节块复制到output
。要查看:
$ stat output
File: ouput
Size: 4294967296 Blocks: 8388616 IO Block: 4096 regular file
--omitted--
你可以看到这个文件已经分配了 8388616 个块,这些块存储的只是从 /dev/zero
复制的 空字节,它们确实占用物理磁盘空间,但它们是存储在磁盘上的空洞(稀疏零)。dd
执行了你所要求的任务,将数据块从一个文件复制到另一个文件。
现在,运行此命令以检测空洞并使文件本身成为空洞文件:
$ fallocate -d output
$ stat output
File: swapfile
Size: 4294967296 Blocks: 0 IO Block: 4096 regular file
--omitted--
你有注意到什么吗?现在块的数量为0,因为只存储空字节的块已经被释放。记住,output
的块并没有存储任何内容,只有一堆空零,fallocate -d
检测到只包含空零的块并将它们释放了,由于该文件的所有块都包含零,它们都被释放了。
同时注意到大小保持不变。这是文件的逻辑(虚拟)大小,而不是它在磁盘上的大小。重要的是要知道,output
现在不占用任何物理存储空间,它没有分配任何块,因此它实际上不使用磁盘空间。运行 fallocate -d
后保留了大小,所以当您稍后从文件中读取时,您会在运行时获得文件系统生成的空字节。然而,output
的物理大小为零,它不使用任何数据块。
记住,当您读取 output
文件时,文件系统会动态生成空字节,它们实际上没有物理存储在磁盘上,并且 stat
报告的文件大小是逻辑大小,而 output
的物理大小为零。在这种情况下,当进程读取该文件时,文件系统必须生成4G的空字节。
使用dd
来生成一个稀疏文件:
$ dd if=/dev/zero of=output2 bs=1G seek=0 count=0
$ stat
stat output2
File: output2
Size: 4294967296 Blocks: 0 IO Block: 4096 regular file
GNU dd
内部使用lseek
和ftruncate
,因此请查看truncate(2)和lseek(2)。
sudo dd if=/dev/zero of=/swapfile bs=1G count=4
时,这个文件在磁盘上的大小是零,对吗? - Luv33preetsudo dd if=/dev/zero of=/swapfile bs=1G count=4
命令创建文件时,它在磁盘上不会有零大小。因为 dd
将零字节复制到你的文件中。换句话说,你实际上是将 /dev/zero
中的零字节复制到了 /swapfile
中。然而,这个命令 dd if=/dev/zero of=sparse_file bs=1G seek=4 count=0
创建了一个稀疏文件,你可以在两个文件上运行 stat
命令并查看 Blocks
字段的变化。你的命令是创建交换文件的推荐方式。 - GIZ