我的编程空间,编程开发者的网络收藏夹
学习永远不晚

存储基础 | 神奇!我的文件有个“洞”

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

存储基础 | 神奇!我的文件有个“洞”

本文转载自微信公众号「奇伢云存储」,作者奇伢 。转载本文请联系奇伢云存储公众号。

 

聊聊背景

文件还能打洞?

支持稀疏文件语义的文件系统就可以。

支持稀疏语义的文件系统有什么基本特征?

  • 实现 fallocate 接口,能够满足文件空间预分配和打洞;
  • 实现 fiemap 的功能,返回文件的具体物理块分配信息;

打洞是什么意思?

英文是“punch hole”,就是在保证文件其他属性不变(比如,文件大小,inode 编号,权限等等)的条件下,主动释放一段文件所占的物理空间。

关于承诺的语义?

文件系统:punch hole 成功,文件系统可能释放,也可能没释放这部分空间,此结果不对用户承诺。

程序猿:反而是程序猿要遵守承诺,一旦 puhch hole 成功,用户将不能对这部分数据做任何假设,要当它已经没了,无论它是不是真的没了。

创建实分配的文件

为了打洞,我们需要先创建一个实际占用 4M 的文件,用 dd 命令如下:

  1. root@ubuntu:~/temp# dd if=/dev/urandom of=./test.txt.4M bs=1M count=4 

可以用 du 命令看一下实际的物理空间:

  1. root@ubuntu:~/temp# du -sh ./test.txt.4M 
  2. 4.0M ./test.txt.4M 

确实是 4M,再用 stat 命令看一下:

  1. root@ubuntu:~/temp# stat ./test.txt.4M 
  2.   File: './test.txt.4M' 
  3.   Size: 4194304    Blocks: 8192       IO Block: 4096   regular file 
  4. Device: fc00h/64512d Inode: 1335860     Links: 1 
  5. Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root) 

文件 Size 4194304 字节,物理占用 Blocks 数是 8192,这里每个 Block 单位是 512 字节,所以物理占用也是 4194304 字节,刚好 4M。

文件打个洞

原材料准备好了,Go 程序怎么给文件打个洞呢 ?

关键在于 fallocate 系统调用。

这是一个跟平台强相关的系统调用,非系统兼容的,下面以 Linux 为例。

由于这个非系统兼容的,类似于这类调用,一般都是用 syscall 这个标准库,直接下发系统调用。

完整程序示例如下:

代码关键几个事项:

  1. 文件头部要加上 // +build linux ;
  2. 调用的是 syscall.Fallocate 接口;

好了,编译一下吧:

  1. go build -gcflags "-N -l" ./punchhole.go 

把编译出的二进制 punchhole 和 test.txt.4M 这两个放在一个目录下,实验一下效果:

  1. root@ubuntu:~/temp# ./punchhole  
  2. 2021/09/08 22:22:21 punch hole success. 

du 看下文件结果:

  1. root@ubuntu:~/temp# du -sh ./test.txt.4M 
  2. 2.0M ./test.txt.4M 

嗷,确实变成了 2M,stat 再看一下:

  1. root@ubuntu:~/temp# stat ./test.txt.4M 
  2.   File: './test.txt.4M' 
  3.   Size: 4194304    Blocks: 4096       IO Block: 4096   regular file 
  4. Device: fc00h/64512d Inode: 1335860     Links: 1 
  5. Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root) 
  6. Access: 2021-07-26 15:39:06.672000000 +0800 

文件大小还是 4M,实际物理空间变成了 2M( 4096 * 512 ),inode 编号、权限都没变。完美,一个空洞文件就诞生了。

文件解析:

这个文件 [ 0,2M ] 的位置是空洞,不占物理空间,读出来会是 0 数据;

[ 2M,4M ] 的数据还是原来从 /dev/urandom 设备读出来的数据,占用实际物理空间;

思考题

抛出几个关键的思考问题,大家可以自行验证。

如果 punchhole 传参是非 4k 对齐的,会怎么样?

划重点:由于文件系统内部都是按照 4k 的单位管理空间的,所以非 4k 对齐的空间是释放不掉的。 punch hole 一定要注意按照 4k 对齐。

特别还要注意一点,虽然非 4k 对齐释放不掉,但是 fallocate 调用也不会报错,这点很重要。最开始就提过,文件系统没给你承诺过啥时候释放啥。

大家可以手动验证下。

文件 test.txt.4M 的 [ 0,2M ] 被打洞之后,这个区域会是什么数据?

**全 0 数据,这个是稀疏文件系统给你的语义。**这个上面也提到过了。

奇伢教你快速用 hexdump 命令看一下:

  1. root@ubuntu:~/temp# hexdump ./test.txt.4M|more 
  2. 0000000 0000 0000 0000 0000 0000 0000 0000 0000 
  3. 0200000 80e3 2c11 f8d8 256b 23b5 a191 fb80 eb5e 
  4. 0200010 f454 e3e2 cb8b 664a a893 6f5a 2df0 99dd 
  5. 0200020 9d30 4f19 144f b4f1 f2cd 7312 c16c 719f 
  6. 0200030 2ef7 3195 48a1 b2c0 03f1 a08a aff3 a022 
  7. ................. 
  8. ................. 

看到了吗?

0x0000000 - 0x0200000 这个区域都是 0 数据。这是 16 进制表示,换算成 10 进制,就是 [ 0 ,2M ] 的区域。

大家也可以用程序去 read 验证下。

总结

总结几个关键点:

文件打洞用的是系统调用 fallocate ;

文件打洞的时候要注意 4k 对齐,不然非对齐部分释放不掉,并且不会报错;

文件系统没承诺什么,所以当没 4k 对齐的时候,虽然没释放空间,也不会报错;

程序猿要遵守承诺,一旦声明了某段空间要释放,以后不能对此空间内容做假设; 

文件打洞的位置,不占物理空间,后续读是返回 0 数据;

 

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

存储基础 | 神奇!我的文件有个“洞”

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

存储基础 | 神奇!我的文件有个“洞”

英文是“punch hole”,就是在保证文件其他属性不变(比如,文件大小,inode 编号,权限等等)的条件下,主动释放一段文件所占的物理空间。

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录