如何以编程方式在 linux 上创建一个完全空的稀疏文件?

How do you programmatically create a completely empty sparse file on linux?

如果你 运行 dd 使用这个:

dd if=/dev/zero of=sparsefile bs=1 count=0 seek=1048576

您似乎获得了一个完全未分配的稀疏文件(这是 ext4)

smark@we:/sp$ ls -ls sparsefile 
0 -rw-rw-r-- 1 smark smark 1048576 Nov 24 16:19 sparsefile

fibmap 同意:

smark@we:/sp$ sudo hdparm --fibmap sparsefile 
sparsefile:
 filesystem blocksize 4096, begins at LBA 2048; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors

无需深入挖掘 dd 的源代码,我正在尝试弄清楚如何在 C 中做到这一点。

我尝试了 fseeking 和 fwriting 零字节,但它什么也没做。 不确定还能尝试什么,我想在我寻找 dd 的内部结构之前有人可能知道。

编辑:包括我的例子...

FILE *f = fopen("/sp/sparse2", "wb");
fseek(f, 1048576, SEEK_CUR);
fwrite("x", 1, 0, f);
fclose(f);

当您使用 write 或最终调用 write 的各种库例程写入文件时,有一个与文件描述符关联的 文件偏移指针 确定字节在文件中的位置。它通常位于最近调用 readwrite 所处理的数据的末尾。但是您可以使用 lseek 将指针定位在文件内的任何位置,甚至可以超出文件的当前末尾。当您在超出当前 EOF 的点写入数据时,被跳过的区域在概念上用零填充。许多系统会优化一些东西,这样跳过的区域中的任何整个文件系统块都不会被分配,从而产生一个 稀疏文件 。尝试读取此类块将成功,返回零。

将充满零的块大小的区域写入文件通常不会生成稀疏文件,尽管某些文件系统可能会这样做。

GNU dd 使用的另一种生成稀疏文件的方法是调用 ftruncatedocumentation 是这样说的:

The ftruncate() function causes the regular file referenced by fildes to have a size of length bytes.

If the file previously was larger than length, the extra data is discarded. If it was previously shorter than length, it is unspecified whether the file is changed or its size increased. If the file is extended, the extended area appears as if it were zero-filled.

对稀疏文件的支持是特定于文件系统的,尽管几乎所有专为 UNIX 设计的本地文件系统都支持它们。

这是对@ 的回答的补充,它是您使用 ftruncate():

请求的功能的简单实现示例
#include <unistd.h>
#include <fcntl.h>

#include <sys/stat.h>

int
main(void)
{
    int file;
    int mode;

    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    file = open("sparsefile", O_WRONLY | O_CREAT, mode);
    if (file == -1)
        return -1;
    ftruncate(file, 0x100000);
    close(file);

    return 0;
}