公众号旧文

为什么文件显示 10GB,但实际只占 4KB

作者:胖子阅读 —

上一篇讲的是:

为什么 Linux 文件实际占用空间通常是 4KB 的整数倍?

文章中有一个反例:

稀疏文件(Sparse File)
例如创建一个:10GB 文件
但是里面大量空间为空。
Linux 可以只分配真正写入的数据 block。

一、文件大小为什么会有两个概念?

Linux 中,一个文件有两个重要属性:

1. 逻辑大小(Logical Size)

也就是:

ls -lh

看到的大小。

例如:

-rw-r--r-- 1 root root 10G test.img

表示这个文件从用户角度看,长度 = 10GB

2. 实际占用空间(Disk Usage)

也就是:

du -h

看到的大小。

例如:

4.0K test.img

表示真正占用磁盘:4KB

于是出现:

逻辑大小:10GB
实际占用:4KB

两个数字完全不同。

二、Linux 为什么允许这样?

关键在于,文件内容和磁盘 block 不是一一对应的

普通文件:

例如:

hello.txt

内容:

Hello Linux

文件系统:

inode
 |
 +--- block 1
      Hello Linux

但是稀疏文件,例如:

test.img

逻辑上:

0GB -------------------- 10GB

但是实际:

block 1
|
数据

中间大量区域:

没有分配 block

文件系统只记录:这里没有数据,读取时返回 0。

三、如何创建一个稀疏文件?

例如创建一个 10GB 文件:

dd if=/dev/zero of=test.img bs=1 count=1 seek=10G

查看:

ls -lh test.img

结果:

10G test.img

但是:

du -h test.img

结果:

4.0K test.img

为什么?

因为命令做的事情,不是写入10GB数据。

而是:

  1. 写入1个字节
  2. 把文件位置移动到10GB处
  3. 告诉 Linux:这个文件结束位置在这里

于是 Linux 创建了一个10GB长度的文件

但是只分配了一个block。

四、读取不存在的 block 会发生什么?

假设文件:

10GB

但是只有:

第0个block

有数据。

程序读取:

5GB位置

文件系统发现:这里没有 block。

Linux 返回:

0000000000000000

也就是全部为0。

所以稀疏文件实际上是用“没有存储”表示“大量连续的0”。

五、稀疏文件有什么用?

1. 虚拟机磁盘

这是最常见场景。

例如创建:

虚拟机硬盘:100GB

但是系统刚安装:

实际使用:8GB

如果普通文件直接占:

100GB

浪费空间。

使用稀疏文件:

虚拟磁盘:100GB
实际:8GB

随着使用增长。

2. 云服务器镜像

云厂商创建:

200GB 云硬盘

实际上用户可能只用了:

30GB

底层存储可以节省大量空间。

3. 数据库文件

数据库经常提前申请空间

例如:

100GB 数据文件

避免频繁扩容。

但是实际数据可能:

20GB

六、为什么不是所有文件都使用稀疏?

因为稀疏文件也有成本。

普通文件:

block1
block2
block3

连续。

稀疏文件:

block1
空洞
空洞
block5

读取时文件系统需要判断这个位置有没有真实 block。

增加管理复杂度。

七、如何判断一个文件是不是稀疏文件?

看:

ls -lh 文件

逻辑大小:

10G

再看:

du -h 文件

实际占用:

4K

如果:

ls >> du

差距巨大。

基本就是稀疏文件。

八、回到最初的问题

上一篇说:Linux 文件实际占用空间通常是4KB整数倍。

现在这个结论依然正确。

因为稀疏文件实际占用:

4KB

仍然是:

4KB 的整数倍