转自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. JAVA设计模式之:訪问者模式

    訪问者模式: 一个作用于某对象结构中各元素的操作,使你能够在不改变各元素类数据结构的前提下添加作用于这些元素的新操作. 结构对象是訪问者模式必备条件.且这个结构对象必须存在遍历自身各个对象的方法. 适 ...

  2. Linux中grep命令的12个实践例子

    grep是每个Linux发行版都预装的一个强有力的文件模式搜索工具.无论何种原因,如果你的系统没有预装它的话,你可以很容易的通过系统的包管理器来安装它(Debian/Ubuntu系中的apt-get和 ...

  3. iOS开发】之CocoaAsyncSocket使用

    本文介绍了CocoaAsyncSocket库中GCDAsyncSocket类的使用.粘包处理以及时间延迟测试. 一.CocoaAsyncSocket介绍 CocoaAsyncSocket中主要包含两个 ...

  4. codeforces educational round 25

    A 出题人不给样例解释...具体程序 #include<bits/stdc++.h> using namespace std; int n; ]; int main() { scanf() ...

  5. kmp的练习们

    //poj3461 Oulipo //kmp模板 统计子串在母串中的位置 #include<iostream> #include<cstdio> #include<cst ...

  6. 【Codeforces1117C_CF1117C】Magic Ship(构造)

    题目: Codeforces1117C 考的时候很困,开局半小时后才过A,只做出来AB,排名3000+,掉了119--半夜体验极差. 翻译: 你是一个船长.最初你在点 \((x_1,y_1)\) (显 ...

  7. Mac OS安装octave出现的问题-'error:terminal type set to 'unknown'的解决'

    学习Machine learning需要使用Octave语言,毕竟Andrew Ng (恩达.吴)力荐.本机系统Mac OS X EI Capitan, 其实什么系统都无所谓了,安装原理都是一样的. ...

  8. 337 House Robber III 打家劫舍 III

    小偷又发现一个新的可行窃的地点. 这个地区只有一个入口,称为“根”. 除了根部之外,每栋房子有且只有一个父房子. 一番侦察之后,聪明的小偷意识到“这个地方的所有房屋形成了一棵二叉树”. 如果两个直接相 ...

  9. bootstrap 字体颜色 对齐方式

    一:字体代码:作用--颜色 1..text-muted:提示--浅灰色 2..text-primary:主要--蓝色 3..text-success:成功--浅绿色 4..text-info:     ...

  10. JQuery中常用的$.get(),$.post(),$.ajax(),$.getJSON(),load()的详解与区别

    背景:因为最近需要获取本地的数据件进行项目测试,需要用到JQuery实现数据文件的读取,但是由于对JQuery内的获取文件方式不太了解,这次趁着机会进行一下总结.因为该总结是本人根据平常的使用及网上的 ...