深度剖析 Linux cp 命令的秘密( 七 )

  • 你 ls -lh ./test.txt 命令看会发现是一个 100 G 的文件;
  • 但是 du -sh ./test.txt 会发现是一个 0 字节的文件;
  • stat ./test.txt 会发现是 Size: 107374182400 Blocks: 0 的文件;
这就是一个典型的稀疏文件 。size 只是文件的逻辑大小,实际的物理空间占用还是得看 Blocks 这个数值 。
下面这种 1T 的文件,因为只写了头尾 8K 数据,所以只需要分配 2 个 block 存储用户数据即可 。
深度剖析 Linux cp 命令的秘密

文章插图
 
好,我们再深入思考下,文件系统为什么能做到这个?
这也是为什么理解稀疏语义要先了解文件系统的实现的原因 。
  1. 首先,最关键的是把磁盘空间切成离散的、定长的 block 来管理;
  2. 然后,通过 inode 能查找到所有离散的数据(保存了所有的索引);
  3. 最后,实现索引块和数据块空间的后分配;
这三点是层层递进的 。
 
稀疏语义接口 
为了知识的完整性,简要介绍稀疏语义的几个接口:
  1. preallocate(预分配):提供接口可以让用户预占用文件内指定范围的物理空间;
  2. punch hole(打洞):提供接口可以让用户释放文件内指定范围的物理空间;
这两个操作刚好相反 。
预分配的意思是?
就是说,当你创建一个 1T的文件,如果你没写数据,这个时候其实没有分配物理空间的,支持稀疏语义的文件系统会提供一个 fallocate 接口给你,让你实现预分配,也就是说把这 1T 的物理空间现在就分配出来 。
思考:这个有什么好处呢?
  • 第一,如果你命中注定要 1T 的空间,预分配是有好处的,把空间分配的工作量集中在初始化的时候一把做了,避免了实时现场分配的开销;
  • 第二,如果不提前占坑,很有可能等你想要的时候已经没有空间可占用了 。所以你把物理空间先占好,就可以安心使用了;
linux 提供了一个 fallocate 命令,可以用来预分配空间 。
fallocate -o 0 -l 4096 ./test.txt这个命令的意思就是给 text.txt 这个文件 [0, 4K] 的位置分配好物理空间 。
打洞(punch hole) 是干啥的呢?
这个调用允许你把已经占用的物理空间释放掉,从而达到快速释放的目的 。这种操作在虚拟机镜像的场景用得多,通常用于快速释放空间,punch hole 能够让业务更有效的利用空间 。
linux 提供了一个 fallocate 命令也可以用来 punch hole 空间 。
fallocate -p -o 0 -l 4096 ./test.txt这个命令的意思是把 test.txt [ 0, 4K ] 的物理空间释放掉 。
 
Go 语言实现 
稀疏文件本身和编程语言无具体关系,可以用任何语言实现,我下面以 Go 为例,看下稀疏文件的预分配和打洞(punch hole)是怎么实现的 。
预分配实现:
func PreAllocate(f *os.File, sizeInBytes int) error { // use mode = 1 to keep size // see FALLOC_FL_KEEP_SIZE return syscall.Fallocate(int(f.Fd()), 0x0, 0, int64(sizeInBytes))}punch hole 实现:
//  mode 0 change to size                  0x0//  FALLOC_FL_KEEP_SIZE                  = 0x1// FALLOC_FL_PUNCH_HOLE                 = 0x2func PunchHole(file *os.File, offset int64, size int64) error { err := syscall.Fallocate(int(file.Fd()), 0x1|0x2, offset, size) if err == syscall.ENOSYS || err == syscall.EOPNOTSUPP {  return syscall.EPERM } return err}可以看到,本质上都是系统调用 fallocate ,然后带不同的参数而已 。指定文件偏移和长度,就能预分配物理空间或者释放物理空间了 。
这里有一个知识点:punch hole 的调用要保证 4k 对齐才能释放空间 。
举个例子,比如:
punch hole [0, 6k] 的数据,你会发现只有 [0, 4k] 的数据物理块被释放了,[4k, 6k] 所占的 4k 物理块还占着空间呢 。


推荐阅读