Linux 如何创建带有文件孔的文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5315428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:15:51  来源:igfitidea点击:

How to create a file with file holes?

clinux

提问by Amumu

File holes are the empty spaces in file, which, however, doesn't take up any disk space and contains null bytes. Therefore, the file size is larger than its actual size on disk.

文件空洞是文件中的空白空间,但不占用任何磁盘空间并包含空字节。因此,文件大小大于其在磁盘上的实际大小。

However, I don't know how to create a file with file holes for experimenting with.

但是,我不知道如何创建带有文件孔的文件以进行试验。

采纳答案by Omnifarious

Use the ddcommand with a seekparameter.

使用ddseek参数的命令。

dd if=/dev/urandom bs=4096 count=2 of=file_with_holes
dd if=/dev/urandom bs=4096 seek=7 count=2 of=file_with_holes

That creates for you a file with a nice hole from byte 8192 to byte 28671.

这为您创建了一个从字节 8192 到字节 28671 有一个很好的洞的文件。

Here's an example, demonstrating that indeed the file has holes in it (the ls -scommand tells you how many disk blocks are being used by a file):

这是一个示例,证明文件中确实存在漏洞(该ls -s命令会告诉您文件正在使用多少个磁盘块):

$ dd if=/dev/urandom bs=4096 count=2 of=fwh # fwh = file with holes
2+0 records in
2+0 records out
8192 bytes (8.2 kB) copied, 0.00195565 s, 4.2 MB/s

$ dd if=/dev/urandom seek=7 bs=4096 count=2 of=fwh
2+0 records in
2+0 records out
8192 bytes (8.2 kB) copied, 0.00152742 s, 5.4 MB/s

$ dd if=/dev/zero bs=4096 count=9 of=fwnh # fwnh = file with no holes
9+0 records in
9+0 records out
36864 bytes (37 kB) copied, 0.000510568 s, 72.2 MB/s

$ ls -ls fw*
16 -rw-rw-r-- 1 hopper hopper 36864 Mar 15 10:25 fwh
36 -rw-rw-r-- 1 hopper hopper 36864 Mar 15 10:29 fwnh

As you can see, the file with holes takes up fewer disk blocks, despite being the same size.

如您所见,尽管大小相同,但带有孔的文件占用的磁盘块更少。

If you want a program that does it, here it is:

如果你想要一个能做到这一点的程序,这里是:

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, const char *argv[])
{
    char random_garbage[8192]; /* Don't even bother to initialize */
    int fd = -1;
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return 1;
    }
    fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (fd < 0) {
        perror("Can't open file: ");
        return 2;
    }
    write(fd, random_garbage, 8192);
    lseek(fd, 5 * 4096, SEEK_CUR);
    write(fd, random_garbage, 8192);
    close(fd);
    return 0;
}

The above should work on any Unix. Someone else replied with a nice alternative method that is very Linux specific. I highlight it here because it's a method distinct from the two I gave, and can be used to put holes in existing files.

以上应该适用于任何Unix。其他人回复了一个很好的替代方法,非常适合Linux。我在这里强调它是因为它是一种与我给出的两种方法不同的方法,可用于在现有文件中放置孔。

回答by NPE

  1. Create a file.
  2. Seek to position N.
  3. Write some data.
  1. 创建一个文件。
  2. 寻求定位N
  3. 写一些数据。

There will be a hole at the start of the file (up to, and excluding, position N). You can similarly create files with holes in the middle.

在文件的开头会有一个洞(直到但不包括 position N)。您可以类似地创建中间有孔的文件。

The following document has some sample C code (search for "Sparse files"): http://www.win.tue.nl/~aeb/linux/lk/lk-6.html

以下文档有一些示例 C 代码(搜索“稀疏文件”):http: //www.win.tue.nl/~aeb/linux/lk/lk-6.html

回答by ninjalj

Aside from creating files with holes, since ~2 months ago (mid-January 2011), you can punch holes on existing files on Linux, using fallocate(2)FALLOC_FL_PUNCH_HOLELWN article, git commit on Linus' tree, patch to Linux's manpages.

除了创建有孔的文件,从大约 2 个月前(2011 年 1 月中旬)开始,您可以在 Linux 上的现有文件上打孔,使用fallocate(2)FALLOC_FL_PUNCH_HOLELWN 文章Linus 树上的 git commit补丁到 Linux 的联机帮助页

回答by clasnake

The problem is carefully discussed in section 3.6 of W.Richard Stevens famous book "Advanced Programming in the UNIX Environment" (APUE for short). The lseek funstion included in unistd.h is used here, which is designed to set an open file's offset explicitly. The prototype of the lseek function is as follows:

这个问题在 W.Richard Stevens 的名著《Advanced Programming in the UNIX Environment》(简称 APUE)的 3.6 节中有详细的讨论。此处使用了 unistd.h 中包含的 lseek 函数,它旨在显式设置打开文件的偏移量。lseek函数的原型如下:

off_t lseek(int filedes, off_t offset, int whence);

Here, filedes is the file descriptor, offset is the value we are willing to set, and whence is a constant set in the header file, specifically SEEK_SET, meaning that the offset is set from the beginning of the file; SEEK_CUR, meaning that the offset is set to its current value plus the offset in the arguement list; SEEK_END, meaning that the file's offset is set the the size of the file plus the offset in the arguement list.

这里filedes是文件描述符,offset是我们愿意设置的值,whence是头文件中设置的一个常量,具体是SEEK_SET,表示从文件开头设置偏移量;SEEK_CUR,表示偏移量设置为其当前值加上参数列表中的偏移量;SEEK_END,意味着文件的偏移量设置为文件的大小加上参数列表中的偏移量。

The example to create a file with holes in C under UNIX like OSs is as follows:

在类似 UNIX 的操作系统下,在 C 中创建有孔文件的示例如下:

/*Creating a file with a hole of size 810*/
#include <fcntl.h>

/*Two strings to write to the file*/    
char buf1[] = "abcde";
char buf2[] = "ABCDE";

int main()
{
    int fd; /*file descriptor*/

    if((fd = creat("file_with_hole", FILE_MODE)) < 0)
        err_sys("creat error");
    if(write(fd, buf1, 5) != 5)
        err_sys("buf1 write error");
    /*offset now 5*/

    if(lseek(fd, 815, SEEK_SET) == -1)
        err_sys("lseek error");
    /*offset now 815*/

    if(write(fd, buf2, 5) !=5)
        err_sys("buf2 write error");
    /*offset now 820*/

    return 0;
}

In the code above, err_sys is the function to deal with fatal error related to a system call.

在上面的代码中,err_sys 是处理与系统调用相关的致命错误的函数。