Golang 和稀疏文件

点击上方蓝色“飞雪无情”关注我的公众号,设个星标,第一时间看文章

在操作系统中,有一种特殊的文件,看着很大,但是实际占用磁盘的空间却很少,这种文件就是稀疏文件。

这种文件的原理其实就是标记文件字节的内容为空(可以理解为NULL,但不是0),为空的内容不会真实的占用磁盘空间,所以也称为打洞,就像就一张纸片(文件)上打了一个个洞,这些洞没有存储数据,所以不占用空间。

生成一个稀疏文件

当知道了稀疏文件的原理后,就很容易的生成一个稀疏文件了。下面我使用Go语言生成一个1GB大小的稀疏文件,但是它的实际磁盘占用空间为0。

func main() {
   sparseFile, err := os.Create("sparse_file")
   if err != nil {
      log.Fatalln(err)
   }
   sparseFile.Truncate(1 << 30)
   sparseFile.Close()
}

使用 Truncate 方法设置文件的大小,然后直接Close退出,就可以得到一个稀疏文件。

➜  hello ls -ls sparse_file 
0 -rw-r--r-- 1073741824 Aug 22 22:19 sparse_file

通过 ls -ls 命令,可以看下这个文件的基本信息。注意这里要留意第一个数字 0 表示该文件实际占用的磁盘空间大小,是0字节。 1073741824 表示该文件的大小,是1GB。
看,对吧,一个1GB大小的文件,实际占用才0字节。

除了 ls -ls 命令,还有 du 命令可以查看占用的实际大小。

➜  hello du sparse_file 
0       sparse_file

写入一些字节的稀疏文件

我们也可以创建已经写入一些字节的稀疏文件,这个使用,对于打洞的内容,使用 Seek 方法跳过即可。

func main() {
   sparseFile, err := os.Create("sparse_file")
   if err != nil {
      log.Fatalln(err)
   }
   sparseFile.Truncate(1 << 30)
   sparseFile.Write([]byte{0x01})
   sparseFile.Seek(1<<30-1, 0)
   sparseFile.Write([]byte{0x02})
   sparseFile.Close()
}

以上代码同样创建了1GB大小的稀疏文件,但是只有第1个字节和最后1个字节写了内容。 Seek 是一个很好的方法,他可以让你跳来跳去,在特定的位置写入你想写入的内容,并且保持稀疏文件的特性。

哪些系统支持稀疏文件

其实现在我们用到的大多数文件系统都支持稀疏文件,比如Windows的NTFS、Linux的Ext4、MacOS的APFS都支持稀疏文件。

这里需要注意的是苹果从2016年宣布的APFS文件系统,如果你的是早期的苹果电脑,可能会不支持。

扫描二维码关注公众号,回复: 15401054 查看本文章

以类Unix系统为例,即使你不用Go语言,也可以很轻松的创建一个稀疏文件,比如:

➜  dd of=sparse-file bs=1k seek=5120 count=0

以上就创建了一个5M的文件,但是实际的磁盘占用空间为0。

稀疏文件的应用

了解了稀疏文件的特点,你应该可以想出一些稀疏文件的使用场景了。

没错,就是那些将来是大文件,但是现在还没那么大的文件。对于这类场景,稀疏文件再适合不过,甚至你可以创建比你的磁盘还大的稀疏文件。

比如磁盘镜像,这在虚拟机中很常用。我们想创建一个500G大小的磁盘,但是现在又不想它占用这么多空间,用多少就占用多少,那么把稀疏文件作为磁盘镜像尤其合适。

比如内存快照,这类在虚拟机中用的比较多。一个内存10GB的虚拟机,我们想把内存数据做个快照,但是内存里的数据是不固定的,但是最大只有10GB。

这时候就可以创建一个10GB的稀疏文件,把虚拟机的内存数据写到这个稀疏文件即可,在写入数据的时候,只写非零的字节数据,这样就可以减少磁盘占用。

这里和Golang的结合可以参考syscall.Mmap系统调用,你可以自己试试,这里不再举例。

func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error)

小结

稀疏文件在很多特定的场景都很好用,但是它也不是完美无缺的。比如在你重写文件的时候,磁盘可能「突然」会满;复制、打包、远程传输的时候可能会丢失稀疏文件的特性。

但是不管怎么说,这是一个很好的文件特定,尤其是在磁盘镜像、快照、日志等场景,尤其合适,善于使用它们,会有意想不到的收获。

f06bcc2265efe8391fa858dbdc9ed85b.png

扫码关注

分享、点赞、在看就是最大的支持

猜你喜欢

转载自blog.csdn.net/flysnow_org/article/details/126552675