公众号旧文
为什么文件显示 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个字节
- 把文件位置移动到10GB处
- 告诉 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 的整数倍