lseek与常规文件的稀疏文件比较导致意外结果?

时间:2017-07-10 13:55:26

标签: c unix

据我了解,我一直在阅读高级的unix编程书。将lseek与文件一起使用并创建一个孔应该使用更少的磁盘空间,因为磁盘上没有记录孔并且孔中填充了零。

然而,我创建了两个文件,一个带孔,一个没有,但是没有孔的文件使用的磁盘空间少于带孔的文件。我想我可能会在代码中搞砸了,但是我不确定我是如何得出这些结果的。因为这似乎与我对文件漏洞的理解相矛盾。这两个文件不应该大小相同吗?

我可能完全从根本上忽略了lseek的使用点?如果是这样,请随意投票,因为我知道只允许最高质量的帖子。并解释我在这里缺少的东西?感谢。

使用lseek的代码

#include "apue.h"
#include <fcntl.h>

char buf1[] = "abcdefghik";
char buf2[] = "ABCDEFGHIJ";

int main (void)
{
    int fd;

    if((fd = creat("file.hole" , FILE_MODE)) < 0)
            err_sys("creat error");

    if(write(fd , buf1 , 10) != 10)
            err_sys("buf1 write error");

    //offset now = 10 becaues we wrote 10 bytes

    if(lseek(fd , 16384 , SEEK_SET) == -1)
            err_sys("lseek error");
    /*offset now = 16384 there is now a hole*/

    if(write(fd , buf2 , 10) != 10)
            err_sys("buf2 write error");
    /*offset now 16384 + 10 bytes = 16394*/

    exit(0);

//now have a gap in file, however this gap is not written to the disk. so doesn't take up all that space on the disk
}

没有lseek的代码

#include "apue.h"
#include <fcntl.h>

char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";

int main (void){
    int fd;

    //creating new file
    if((fd = creat("file.nohole" , FILE_MODE)) < 0)
            err_sys("create error");

    //writing 10 bytes of buf1
    if(write(fd,buf1,10) != 10)
            err_sys("write buf1 error");
    //writing 10 bytes of buf2
    if(write(fd,buf2,10) != 10)
            err_sys("write buf2 error");

    exit(0);

    //no hole in the file.
}

od -c file.hole(检查内容)

0000000   a   b   c   d   e   f   g   h   i   k  \0  \0  \0  \0  \0  \0
0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0040000   A   B   C   D   E   F   G   H   I   J
0040012

od -c file.nohole(检查内容)

0000000   a   b   c   d   e   f   g   h   i   j   A   B   C   D   E   F
0000020   G   H   I   J
0000024

比较两个文件 - ls -ls file.hole file.nohole

28 -rw-r--r-- 1 sam sam 16394 Jul 10 14:09 file.hole
12 -rw-r--r-- 1 sam sam    20 Jul 10 14:32 file.nohole

1 个答案:

答案 0 :(得分:1)

带孔的文件将数据存储在两个独立的磁盘块上。

没有空洞的文件将数据存储在一个磁盘块上。

ls报告的大小是文件中的字节数,而不是磁盘块中存储的字节数。丢失的字节都是零,因为od -c的输出清楚。

请注意,使用lseek()的重点不是在文件中创建漏洞。这些是实现细节。使用lseek()的原因是将读/写位置放在要读取或写入下一个文件的文件中。例如,在具有固定大小记录的文件中,您可以使用lseek(fd, N * sizeof(struct Record), SEEK_SET)到达第N条记录,然后在该位置读取(或写入)数据。