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

如果你用这个运行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中做到这一点。

我尝试了fgetsking和写零字节,但它什么都没做。 不知道还有什么可以尝试的,我觉得有人可能知道之前我追捕dd的内脏。

编辑:包括我的例子…

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

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

将文件块大小为零的文件写入文件通常不会生成稀疏文件,尽管某些文件系统可以执行此操作。

生成GNU dd使用的稀疏文件的另一种方法是调用ftruncate 。 文档说这个:

ftruncate()函数使得由fildes引用的常规文件具有长度字节的大小。

如果以前的文件大于长度,则额外的数据将被丢弃。 如果它以前比长度更短,则不确定文件是否更改或者文件大小是否增加。 如果文件被扩展,扩展区域显示为零填充。

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

这与@ MarkPlotnick的答案是互补的,它是使用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; }