8

如果你用这个运行 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);
4

2 回答 2

10

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

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

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

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

如果文件先前大于长度,则丢弃多余的数据。如果它以前比长度短,则未指定文件是更改还是增加了大小。如果文件被扩展,则扩展区域看起来好像是用零填充的。

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

于 2015-11-24T21:57:02.367 回答
8

这是对@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;
}
于 2015-11-24T22:05:31.497 回答