You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何du -sh输出的内存映射文件大小不正确?

为什么NFS上的内存映射文件du -sh和ls/stat大小显示不一致?

这个问题我之前处理过,本质是稀疏文件特性加上NFS的块分配逻辑共同导致的,咱们一步步理清楚:

核心原因:命令统计的是不同维度的大小

先明确几个命令的统计逻辑差异:

  • du -sh:默认统计的是文件实际占用的磁盘物理块大小——也就是真正写到磁盘上的存储空间,未分配的空块不会被计算。
  • ls -la/stat:显示的是文件的逻辑大小——也就是文件系统记录的文件总长度,不管这些空间有没有实际分配磁盘块。
  • du -bh:-b参数强制让du按字节统计文件的逻辑大小,所以结果会和ls/stat完全一致。

内存映射文件为什么会触发这个现象?

当你通过内存映射创建文件时,系统默认会采用延迟分配的策略:

  1. 一开始只在文件系统中记录文件的逻辑总大小,但并不会立刻分配所有对应的磁盘块。
  2. 只有当你真正往映射的内存区域写入数据时,系统才会按需为写入的部分分配实际磁盘块。
  3. 再加上NFS的分布式特性:客户端可能先在本地缓存中标记文件的逻辑大小,但实际还没向NFS服务器申请所有磁盘块,这就导致服务器端的du只能统计已经实际分配的块,而客户端的ls/stat显示的是预先定义的逻辑大小。

验证与解决方法

验证是否为稀疏文件

执行file foo.dat,如果输出包含sparse file,就说明这是稀疏文件:

file foo.dat
# 示例输出:foo.dat: regular file, sparse file

让du显示逻辑大小

如果需要让du显示和ls一致的逻辑大小,可以使用--apparent-size参数:

du --apparent-size -h foo.dat
# 输出会和ls -la一致:718M foo.dat

强制分配所有磁盘块(如果需要)

如果你希望文件实际占用的空间和逻辑大小一致,可以读取整个文件触发块分配,或者用fallocate命令(CentOS7支持):

# 方法1:读取整个文件
dd if=foo.dat of=/dev/null bs=1M

# 方法2:用fallocate直接分配块
fallocate -l 752562176 foo.dat

执行后再用du -sh查看,大小就会和ls一致了。

内容的提问来源于stack exchange,提问作者david

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:36:48