用fallocate进行"文件预留"或"文件打洞"【转】
转自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进行"文件预留"或"文件打洞"【转】的更多相关文章
- UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)
前面[UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理]章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例. 原代码地址:ht ...
- 从java文件和CS文件里查询方法使用次数工具
前几天,领导让我找一下老系统(Java)里getRemoteUser方法都哪个文件用了,package是什么,方法被调用了多少次,当时因为着急,所以,直接人工找的,但是以后要是再出现,人工找就太讨厌了 ...
- java中的文件读取和文件写出:如何从一个文件中获取内容以及如何向一个文件中写入内容
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.Fi ...
- C#的Process类调用第三方插件实现PDF文件转SWF文件
在项目开发过程中,有时会需要用到调用第三方程序实现本系统的某一些功能,例如本文中需要使用到的swftools插件,那么如何在程序中使用这个插件,并且该插件是如何将PDF文件转化为SWF文件的呢?接下来 ...
- Excel文件转plist文件出现的文件编码问题
今天在测试时遇到了需要将大量整理好的Excel数据转换为plist文件的情况.百度了一下教程,发现虽然别人也遇到过类似的情况,但是有些讲的还是不够细致.所以做如下整理. 百度到的内容中有使用Mes ...
- 使用java读取文件夹中文件的行数
使用java统计某文件夹下所有文件的行数 经理突然交代一个任务:要求统计某个文件夹下所有文件的行数.在网上查了一个多小时没有解决.后来心里不爽就决定自己写一个java类用来统计文件的行数,于是花了两个 ...
- 【Linux】Linux统计文件夹、文件数量的命令
# 查看当前目录下的文件数量(不包含子目录中的文件) ls -l|grep "^-"| wc -l # 查看当前目录下的文件数量(包含子目录中的文件) 注意:R,代表子目录 ls ...
- python 根据现有文件树创建文件树
# -*- coding: utf-8 -*- import os, errno def fileName(path):#获取文件夹 str = '' for i in range(1,len(pat ...
- libreoffice转换文件为pdf文件乱码问题解决办法
最近系统需要一个office文件预览功能 解决方案为使用libreoffice将office文件转换为pdf文件,然后使用swftools将pdf文件转换为swf文件 最后在前台使用flexpaper ...
随机推荐
- Struts2之类型转换器的使用
一.学习案例:通过在输入页面(input.jsp)用同一个输入框同一时候输入username和password,通过类型转换器在输出页面(output.jsp)分别输出username和passwor ...
- Date类型转换为Integer类型
Date类型转换为Integer类型: Integer date = Integer.valueOf(String.valueOf(new SimpleDateFormat("yyyyMMd ...
- hdu 1799 (循环多少次?)(排列组合公式)
循环多少次? Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- npm/bower/brew
npm: npm(node package manager)node包管理器,用来下载发布第三方工具包,例如:代码的压缩.合并.编译的插件包.主要功能:安装.卸载.更新.查看.搜索.发布等 npm的具 ...
- 【Ubuntu】无法挂载磁盘
我的电脑分了三个分区,A,B,C,其中A和B是Windows盘,C是ubuntu系统盘 某日发现A ,B盘没法进入了,在文件管理器中点一下,没有反应.于是右击盘符,点击挂载,跳出错误信息: (划重点) ...
- bootstrap table load数据
直接load数据: $("#button").click(function(){ var name=$("input[name='name']").val(); ...
- Android 体系结构介绍
转自:http://blog.sina.com.cn/s/blog_4bc996c40100fawo.html 第一.操作系统层(OS)第二.各种库(Libraries)和Android 运行环境(R ...
- bzoj3545
线段树合并+离线+启发式合并 半年前这道题t成狗... 离线的做法比较好想,按照边的权值排序,询问的权值排序,然后枚举询问不断加边,加到上限后查找第k大值,这里平衡树,权值线段树都可以实现. 那么我们 ...
- Sqlserver日期操作
Sqlserver日期操作 select GETDATE() as '当前日期', DateName(year,GetDate()) as '年', DateName(month,GetDate()) ...
- django - request.POST和request.body获取值时出现的情况
django request.POST / request.body 当request.POST没有值 需要考虑下面两个要求 1.如果请求头中的: Content-Type: application/ ...