学习笔记:linux之⽂件空洞
⽂件空洞
我们知道lseek()系统调⽤可以改变⽂件的偏移量,但如果程序调⽤使得⽂件偏移量跨越了⽂件结尾,然后再执⾏I/O操作,将会发⽣什么情况? read()调⽤将会返回0,表⽰⽂件结尾。令⼈惊讶的是,write()函数可以在⽂件结尾后的任意位置写⼊数据。在这种情况下,对该⽂件的下⼀次写将延长该⽂件,并在⽂件中构成⼀个空洞,这⼀点是允许的。从原来的⽂件结尾到新写⼊数据间的这段空间被成为⽂件空洞。调⽤write后⽂件结尾的位置已经发⽣变化。
在Linux系统之中,⽂件结束符EOF根本不是⼀个字符,⽽是当系统读取到⽂件结尾,所返回的⼀个信号值(也就是-1),⾄于系统怎么知道⽂件的结尾,资料上说是通过⽐较⽂件的长度。
⽂件空洞占⽤任何磁盘空间,直到后续某个时点,在⽂件空洞中写⼊了数据,⽂件系统才会为之分配磁盘块。空洞的存在意味着⼀个⽂件名义上的⼤⼩可能要⽐其占⽤的磁盘存储总量要⼤(有时⼤出许多)。向⽂件空洞中写⼊字节,内核需要为其分配存储单元,即使⽂件⼤⼩不变,系统的可⽤磁盘空间也将减少。这种情况并不常见,但也需要了解。
ls -l file 查看⽂件逻辑⼤⼩
du -c file 查看⽂件实际占⽤的存储块多少
od -c file 查看⽂件存储的内容
空洞⽂件就是有空洞的⽂件,在⽇常的常识中,我们使⽤的⽂件存放在硬盘分区上的时候,有多⼤的内容就会占⽤多⼤的空间,⽐如这个⽂本⽂件⾥⾯写有1000个asc 字符,那么就会占⽤磁盘上1000B的存储空间,为了便于管理⽂件,⽂件系统都是按块⼤⼩来分配给⽂件的,假如这个⽂件系统⼀个块是4096的话,那么这个⽂件就会占⽤⼀个块的,⽆论实际的内容是1B还是4000B.如果我们有⼀个4MB的⽂件,那么它会在分区中占⽤:4MB/4096B=1000个块.
现在我们先做⼀个实际的⽆空洞⽂件来看看:
#dd if=/dev/urandom of=testfile1 bs=4096 count=1000
这个命令会从/dev/urandom⽂件复制1000个块,每块⼤⼩4096,到testfile1⽂件去.
好了,我们已经有了testfile1这么⼀个4M的⽂件了,⾥⾯填充了⼀些随机的内容,你可以more⼀下.
然后⽤ls -l查看这个⽂件的⼤⼩是4096000,⽤du -h testfile1来查看的话,⽂件占⽤的磁盘⼤⼩是4M,两者是⼀样的.
linux怎么读取文件
下来是我们的重点,空洞⽂件,假如我们有⼀个⽂件,它有4M的⼤⼩,但是它⾥边很⼤⼀部分都是没有存放数据的,这样可不可以呢?试⼀下:
#dd if=/dev/urandom of=testfile2 bs=4096 seek=999 count=1
这个命令跟前⼀个命令相似,不同的是,它其实复制了1个块的内容,前⾯的999个块都跳过了.
我们ls -l⼀下,发现⽂件的⼤⼩还是4096000,⽤du -h testfile2查看,占⽤的块⼤⼩是4K
我们发现,虽然⽂件是4M,但是实际在磁盘上只占⽤了4K的⼤⼩,这就是空洞⽂件的神奇之处.
实际中的空洞⽂件会在哪⾥⽤到呢?常见的场景有两个:
⼀是在下载电影的时候,发现刚开始下载,⽂件的⼤⼩就已经到⼏百M了.
⼆是在创建虚拟机的磁盘镜像的时候,你创建了⼀个100G的磁盘镜像,但是其实装起来系统之后,开始也不过只占⽤了3,4G的磁盘空间,如果⼀开始把100G都分配出去的话,⽆疑是很⼤的浪费.
然后讲⼀下底层的实现吧,其实这个功能关键得⽂件系统⽀持,貌似FAT就不可以吧,linux下⼀直都很好的⽀持这⼀特性,我们举个最简单的ext的例⼦吧,ext中记录⽂件实际内容的对应信息的东东是⼀个叫索
引表的东西,⾥⾯有⼗⼏个条⽬,每个条⽬存放对应⽂件内容块的块号,这样就可以顺序到对应的⽂件内容了,⼤家可能说,⼏M的⼀个⽂件,⼗⼏个项哪够啊,不必担⼼,⼀般索引表前⾯⼏个项⽬是直接指向⽂件内容的,如果这⼏个不够的话,往后的第⼀个项⽬不会指向⽂件内容块,⽽会指向⼀个存放项⽬的块,这样⼀下多出N个项⽬来,如果这样还不够,下⾯的那个是存放指向指向的项⽬,不好意思,我也绕晕了,总之,前⾯的是直接指向,下⾯这个是⼆级指向,再下⾯的是⼆级指向,以此类推,这样,⽂件系统就可以处理T数量级别的⽂件,看下图:
到了空洞⽂件这⾥呢,我们只需要把指向没有⽂件内容部分的索引项⽬置NULL就好了,这样就不会指向实际的数据块了,也不会占⽤磁盘空间了,就这么easy~
⾄于btrfs这些新⼀代⽂件系统呢,在空洞⽂件这⾥的原理跟ext还是类似的.
最后介绍⼀下linux对空洞⽂件的处理,经过我最近的⼀些测试所得:
在同⼀⽂件系统ext4下,cat⼀个空洞⽂件到新⽂件,新⽂件不再是空洞⽂件,cp⼀个空洞⽂件到新⽂件,新⽂件仍然是空洞⽂件.
在btrfs跟ext4之间做的结果同上⾯是⼀致的,但是在不同⽂件系统之间cp,因为不同⽂件系统分配的最⼩单元不同,所以du结果会不同.
在nfs的客户端下,在nfs⽬录下去cp,新⽂件仍然是空洞⽂件但是cp会逐个的去⽐较⽂件的内容,所以,受⽹络状况搞得影响,过程有时候会很慢.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论