转自uestc-leon的博客

内容作了一些修改,查看原文请访问uestc-leon

1. 什么是空洞文件?

“在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。”

如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。大部分文件系统是不占用的。

2. 怎么获得一个空洞文件?

以Linux来说,使用lseek或truncate到一个固定位置生成的“空洞文件”是不会占据真正的磁盘空间的。

空洞文件特点就是offset大于实际大小,也就是说一个文件的两头有数据而中间为空,以‘\0‘填充。那文件系统会不会不做任何处理的将其存放在硬盘上呢?大部分文件系统是不会将其存放在硬盘上。

3. 文件预留

为什么需要文件预留

在开发过程中有时候需要为某个文件快速地分配固定大小的磁盘空间,为什么要这样做呢? **

1. 可以让文件尽可能的占用连续的磁盘扇区,减少后续写入和读取文件时的磁盘寻道开销;

2. 迅速占用磁盘空间,防止使用过程中所需空间不足。

3. 后面再追加数据的话,不会需要改变文件大小,所以后面将不涉及metadata的修改

前面提到使用lseek或truncate到一个固定位置生成的“空洞文件”是不会占据真正的磁盘空间的。

快速的为某个文件分配实际的磁盘空间在Linux下可通过fallocate(对应的posix接口为posix_fallocate)系统调用来实现,大部分主流文件系统如ext4,xfs还是支持fallocate

4. fallocate的mode

mode决定了fallocate的行为。

**Allocating disk space **

这是默认的操作,对应mode等于0。它所作的工作是如果分配从offset开始到offset+len的一段空间,这个是真的分配磁盘空间,不是hole,新分配的空间以0填充数据。当然这个操作一般在offset+len大于现有文件长度时才会起到增加文件数据空间的作用。
一般情况下新增加空间后文件的size也会随着调整,但是有一个特殊情况,就是当FALLOC_FL_KEEP_SIZE出现在mode中时,在增加文件空间后不会改变文件的size。这样的操作算是一种在文件结尾处的预分配,对于后期的append写入操作有优化作用。

Deallocating file space

释放文件的某段范围的磁盘空间 (文件打洞)
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE
此mode虽然并不会改变文件的大小,但其实却释放了offset和len所在范围的磁盘块,将它们归还给了文件系统。fallocate成功后,后续对offset和len所在的文件范围进行读操作,将会读到0。

5. fallocate命令简单使用

NAME

fallocate - preallocate space to a file

SYNOPSIS

fallocate [-n] [-p] [-o offset] -l length filename
fallocate -x [-o offset] -l length filename

DESCRIPTION

fallocate用于预分配块到文件。对于支持fallocate系统调用的文件系统,这是通过分配块并将它们标记为未初始化的,从而快速完成的,不需要IO到数据块。这比用0填充文件要快得多。
在Linux内核v2.6.31的情况下,fallocate系统调用由btrfs、ext4、ocfs2和xfs filesystems支持。
fallocate返回的退出代码在成功时是0,而失败则是1。

OPTIONS

The length and offset arguments may be followed by the multiplicative suffixes KiB=1024, MiB=1024*1024, and so on for GiB,  TiB,  PiB,  EiB,  ZiB  and  YiB  (the "iB" is optional, e.g. "K" has the same meaning as "KiB") or the suffixes KB=1000, MB=1000*1000, and so on for GB, TB, PB, EB, ZB and YB.

-l, --length length		##分配多少空间
-o, --offset offset ##设置偏移量

EXAMPLE

##创建完成后,可以将它们进行格式化,并当做文件系统进行挂载。我格式化成ext4之后,可以看到superblock、block group等信息,挂载之后使用df -h可以看到这个分区的大小是:前者10G,后者30G。
##而且这个大文件所在目录的文件系统的空间使用率几乎没有增加(只增加了100+M),我认为这是因为这个文件是空洞文件,虽然分配了一堆block的,但是没有使用,使用的时候将bmap标记为使用之后,空间就会增加了。
fallocate -l 10G bigfile ##创建一个10G的文件(使用ll查看,大小为10G) ##挂在之后看到分区,这个分区是10G
fallocate -l 10G -o 20G bigfile2 ##创建一个10G的文件,偏移量为20G(使用ll查看,大小为30G;通过df -h看到只占用了10G;通过du看到只占用了100+M的空间)

6. 创建大文件

但是这样为实际写入硬盘,文件产生速度取决于硬盘读写速度,如果欲产生超大文件,速度很慢

dd if=/dev/zero of=test bs=1M count=1000
会生成一个1000M的test文件,文件内容为全0(因从/dev/zero中读取,/dev/zero为0源)

在某种场景下,我们只想让文件系统认为存在一个超大文件在此,但是并不实际写入硬盘,则可以:

dd if=/dev/zero of=test bs=1M count=0 seek=100000
此时创建的文件在文件系统中的显示大小为100000MB,但是并不实际占用block,因此创建速度与内存速度相当
seek的作用是跳过输出文件中指定大小的部分,这就达到了创建大文件,但是并不实际写入的目的
当然,因为不实际写入硬盘,所以你在容量只有10G的硬盘上创建100G的此类文件都是可以的

fallocate、truncate 以及GNU dd的seek扩展命令都可以实现创建空洞文件的效果

fallocate -l 10G bigfile
truncate -s 10G bigfile
dd of=bigfile bs=1 seek=10G count=0

文件系统对于这样创建的文件有特殊处理,叫稀疏文件

用fallocate进行"文件预留"或"文件打洞"【转】的更多相关文章

  1. UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)

    前面[UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理]章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例. 原代码地址:ht ...

  2. 从java文件和CS文件里查询方法使用次数工具

    前几天,领导让我找一下老系统(Java)里getRemoteUser方法都哪个文件用了,package是什么,方法被调用了多少次,当时因为着急,所以,直接人工找的,但是以后要是再出现,人工找就太讨厌了 ...

  3. java中的文件读取和文件写出:如何从一个文件中获取内容以及如何向一个文件中写入内容

    import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.Fi ...

  4. C#的Process类调用第三方插件实现PDF文件转SWF文件

    在项目开发过程中,有时会需要用到调用第三方程序实现本系统的某一些功能,例如本文中需要使用到的swftools插件,那么如何在程序中使用这个插件,并且该插件是如何将PDF文件转化为SWF文件的呢?接下来 ...

  5. Excel文件转plist文件出现的文件编码问题

    今天在测试时遇到了需要将大量整理好的Excel数据转换为plist文件的情况.百度了一下教程,发现虽然别人也遇到过类似的情况,但是有些讲的还是不够细致.所以做如下整理.   百度到的内容中有使用Mes ...

  6. 使用java读取文件夹中文件的行数

    使用java统计某文件夹下所有文件的行数 经理突然交代一个任务:要求统计某个文件夹下所有文件的行数.在网上查了一个多小时没有解决.后来心里不爽就决定自己写一个java类用来统计文件的行数,于是花了两个 ...

  7. 【Linux】Linux统计文件夹、文件数量的命令

    # 查看当前目录下的文件数量(不包含子目录中的文件) ls -l|grep "^-"| wc -l # 查看当前目录下的文件数量(包含子目录中的文件) 注意:R,代表子目录 ls ...

  8. python 根据现有文件树创建文件树

    # -*- coding: utf-8 -*- import os, errno def fileName(path):#获取文件夹 str = '' for i in range(1,len(pat ...

  9. libreoffice转换文件为pdf文件乱码问题解决办法

    最近系统需要一个office文件预览功能 解决方案为使用libreoffice将office文件转换为pdf文件,然后使用swftools将pdf文件转换为swf文件 最后在前台使用flexpaper ...

随机推荐

  1. node.js中的require

    初初接触node.js,印象最深刻的就是开头密密麻麻的require了. 这是什么东西? 其实也没啥大惊小怪的.require就是为了引用别的js文件,利于模块化编程,重用.以及避免过多代码挤在同一个 ...

  2. 1732 Fibonacci数列 2

    1732 Fibonacci数列 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 在“1250 F ...

  3. ubuntu16.04下配置静态ip

    ubuntu下配置静态ip 1.先获取ip基本信息 ifconfig enp3s0 Link encap:以太网 硬件地址 2c:4d:54:65:de:6e inet 地址:192.168.199. ...

  4. E20170618-hm

    sentinel   n. 岗哨,哨兵; node   n. 节点; (计算机网络的) 节点; [医] 结节; 植物的节; traverse  n. 穿过; 横贯,横切; 横木; [建] 横梁; vt ...

  5. Linux学习大纲

  6. 洛谷P2668斗地主(搜索)noip2015

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...

  7. 关于CSS中float的两点心得以及清除浮动的总结

    对一个元素运用float后,该元素将脱离正常文档流,这意味着: 1. 运用float后,该元素不再影响父元素的高度,如果一个元素的所有子元素都是float的话,那么该元素的高度是0,这样后面元素渲染的 ...

  8. [Swift通天遁地]七、数据与安全-(5)高效操作SQLite数据库

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  9. Akka源码分析-local-DeathWatch

    生命周期监控,也就是死亡监控,是akka编程中常用的机制.比如我们有了某个actor的ActorRef之后,希望在该actor死亡之后收到响应的消息,此时我们就可以使用watch函数达到这一目的. c ...

  10. linux 防火墙关闭

     systemctl status firewalld.servicesystemctl status iptables.service关闭防火墙,selinux15:54:43运维-李浩 2017/ ...