【问题标题】:How does stat command calculate the blocks of a file?stat 命令如何计算文件的块?
【发布时间】:2010-11-23 17:25:24
【问题描述】:

我想知道stat 命令如何计算文件的块数。我读到这个article 说:

值 st_blocks 以 512 字节块为单位给出文件的大小。 (这可能小于 st_size/512,例如当文件有漏洞时。)值 st_blksize 给出了高效文件系统 I/O 的“首选”块大小。 (以较小的块写入文件可能会导致读取-修改-重写效率低下。)

但我无法通过自己的测试来验证这一点。

我的文件系统是 ext3。

命令dumpe2fs -h /dev/sda3显示:

...
First block: 0
Block size: 4096
Fragment size: 4096
...

然后我跑

kent@KentT60:~/Desktop$ stat Email
File: `Email'
Size: 965 Blocks: 8 IO Block: 4096 regular file
Device: 80ah/2058d Inode: 746095 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kent) Gid: ( 1000/ kent)
Access: 2009-08-11 21:36:36.000000000 +0200
Modify: 2009-08-11 21:36:35.000000000 +0200
Change: 2009-08-11 21:36:35.000000000 +0200

如果这里的“Blocks”的意思是:“多少个512字节的块”,数字应该是2,而不是8。我以为文件系统的块大小(IO块)是4k。

如果文件系统获取文件Email,它将从磁盘中获取至少4k(8 x 512字节块),这意味着965/512 + 6 = 8。我不确定这个猜测是否正确。

另一个测试:

kent@KentT60:~/Desktop$ stat wxPython-demo-2.8.10.1.tar.bz2
File: `wxPython-demo-2.8.10.1.tar.bz2'
Size: 3605257 Blocks: 7056 IO Block: 4096 regular file
Device: 80ah/2058d Inode: 746210 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kent) Gid: ( 1000/ kent)
Access: 2009-08-12 21:45:45.000000000 +0200
Modify: 2009-08-12 21:43:46.000000000 +0200
Change: 2009-08-12 21:43:46.000000000 +0200


3605257/512=7041.xx = 7042

按照我上面的猜测,这将是 7042 + 6 = 7048。但 stat 结果显示为 7056。

另一个来自互联网的例子https://www.computerhope.com/unix/stat.htm。我将示例粘贴在页面底部:

File: `index.htm'
Size: 17137 Blocks: 40 IO Block: 8192 regular file
Device: 8h/8d Inode: 23161443 Links: 1
Access: (0644/-rw-r--r--) Uid: (17433/comphope) Gid: ( 32/ www)
Access: 2007-04-03 09:20:18.000000000 -0600
Modify: 2007-04-01 23:13:05.000000000 -0600
Change: 2007-04-02 16:36:21.000000000 -0600

在本例中,文件系统块大小为 8k。我想“块”值应该是 16xN,但它是 40。我迷路了......

谁能解释stat如何计算“块”值?

谢谢!

【问题讨论】:

  • stat 的输出有点危险:“Blocks”的块大小为 512 字节,而“IO Block”的块大小通常为 4096 字节(对于 ext4)。我试图在this answer 中了解这一点。

标签: linux filesystems


【解决方案1】:

stat 命令行工具使用stat / fstat 等函数,它们以stat 结构返回数据。 stat 结构的 st_blocks 成员返回:

在磁盘上实际分配的大小为 512 字节的物理块的总数。该字段没有为块特殊文件或字符特殊文件定义。

因此,对于您的“电子邮件”示例,大小为 965,块数为 8,这表明磁盘上物理分配了 8*512=4096 个字节。它不是2的原因是磁盘上的文件系统没有以512为单位分配空间,它显然以4096为单位分配空间。(分配单位可能因文件大小和文件系统复杂程度而异。例如ZFS支持不同的分配单位。)

同样,对于 wxPython 示例,它表示在磁盘上物理分配了 7056*512 字节或 3612672 字节。你明白了。

IO 块大小是“关于 I/O 操作的‘最佳’单元大小的提示”——它通常是物理磁盘上的分配单元。不要混淆IO块和stat用来表示物理大小的块;物理大小的块总是 512 字节。

根据评论更新:

就像我说的,st_blocks 是操作系统指示磁盘上文件使用了多少空间的方式。磁盘上的实际分配单位是文件系统的选择。例如,ZFS 可以有可变大小的分配块,甚至在同一个文件中,因为它分配块的方式:文件开始具有小块大小,并且块大小不断增加,直到它达到一个特定的点。如果文件稍后被截断,它可能会保留旧的块大小。所以根据文件的历史,它可以有多种可能的块大小。所以给定一个文件大小,为什么它有一个特定的物理大小并不总是很明显。

具体示例:在我的 Solaris 机器上,使用 ZFS 文件系统,我可以创建一个非常短的文件:

$ echo foo > test
$ stat test
  Size: 4               Blocks: 2          IO Block: 512    regular file
(irrelevant details omitted)

好的,小文件,2个块,这个文件的物理磁盘使用量是1024。

$ dd if=/dev/zero of=test2 bs=8192 count=4
$ stat test2
  Size: 32768           Blocks: 65         IO Block: 32768  regular file

好的,现在我们看到物理磁盘使用量为 32.5K,IO 块大小为 32K。然后我将它复制到test3 并在编辑器中截断了这个test3 文件:

$ cp test2 test3
$ joe -hex test3
$ stat test3
  Size: 4               Blocks: 65         IO Block: 32768  regular file

现在,这是一个包含 4 个字节的文件 - 就像 test - 但由于 ZFS 文件系统分配空间的方式,它在磁盘上物理使用了 32.5K。块大小会随着文件变大而增加,但不会随着文件变小而减小。 (是的,这可能会导致大量空间浪费,具体取决于您在 ZFS 上执行的文件类型和文件操作,这就是为什么它允许您基于每个文件系统设置最大块大小并动态更改它的原因。)

希望您现在可以理解,文件大小和物理磁盘使用率之间不一定存在简单的关系。即使在上面,也不清楚为什么需要 32.5K 字节来存储大小正好为 32K 的文件 - 似乎 ZFS 通常需要额外的 512 字节来存储自己的额外存储空间。也许它正在使用该存储来存储校验和、引用计数、事务状态 - 文件系统簿记。通过在指定的物理文件大小中包含这些额外内容,ZFS 似乎试图不误导用户关于文件的物理成本。这并不意味着在不了解底层文件系统实现的详细信息的情况下对计算进行逆向工程是微不足道的。

【讨论】:

  • 同意。 st_blocks 仅因历史原因而被称为。不要将其视为块,而是文件使用的磁盘空间量,以 512 字节为单位。 512 字节是一个方便的单位,因为它几乎是任何人使用的最小分配单位。
  • 感谢您的解释。几乎清楚。但仍有疑问。我不确定理解是否正确:st_blocks = (IO 块大小 / 512) *(文件使用了多少 IO 块)。电子邮件示例可以这样解释:(4096/512) * 1 = 8 wxpython 一个不是。因为该文件使用了 881 个 IO 块,并且 (4096/512)*881=7048 而不是 7056。最后一个示例也不是:40 甚至不能完全除以 16 (8192/512).. 是“512bytes”所有系统都一样吗?谢谢
【解决方案2】:

这里我们需要观察一件事,数据块分配是通过以下指定的方式完成的:

1)默认情况下,即使我们写入一个字节的数据,也会为一个文件分配 8 个数据块 在文件中。 2)当我们在文件中添加完 8*4096 字节的数据后,如果我们添加一个额外的字节,那么将再次分配新的 8 个数据块。 所以,总共16个数据块。

如果您理解以上陈述, 然后 -----(在问题中)----- 因此对于 965,默认情况下将分配 8 个数据块,当它恰好是 4*4096=32768 并填充所有这些时,如果我们添加另一个字节,则将分配 8 个数据块,对于 32769 的大小,总共 16 个数据块将被分配。

【讨论】:

  • "...在文件中添加 8*4096 字节的数据...".当stat 写入Blocks: 8 时,这意味着为文件分配了8 个512 字节 的块,而不是8 个4096 字节的块。 IO Block: 4096 指的是首选文件系统块大小,这个块大小在 ext4 上绝不是 512。请参阅我的this answer 了解更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多