使用stat()和ls -s分配的块数不同

时间:2017-04-09 20:56:52

标签: c

我试图使用C来获取分配给文件的块数。我使用了stat结构及其变量st_blocks。然而,与ls -s相比,这返回了不同数量的块。任何人都可以解释这个原因以及是否有办法纠正这个问题?

2 个答案:

答案 0 :(得分:2)

没有差异;只是一个误会。这里有两个单独的“块大小”。使用ls -s --block-size=512也可以使用ls的512字节块大小。

ls -s命令以用户指定的单位(“块”)列出分配给文件的大小,您可以使用--block-size选项指定大小。

struct stat中的st_blocks字段以512字节为单位。

您会看到差异,因为两个“块大小”不一样。它们碰巧被称为同名。

以下是您可以检查此效果的示例。这适用于所有POSIXy / Unixy文件系统(支持sparse file),但不适用于FAT / VFAT等。

首先,让我们创建一个但是一兆字节长的文件,但在开头有一个洞(它们读取零,但实际上并不存储在磁盘上),最后只有一个字节(我将使用{{ 1}})。

我们通过使用'X'跳过文件的第一个1048575字节(创建“漏洞”,因此在支持此类文件系统的文件系统上的稀疏文件)来执行此操作:

dd

我们可以使用stat实用程序来检查文件。格式说明符printf 'X' | dd bs=1 seek=1048575 of=sparse-file count=1 提供文件的逻辑大小(1048576),%s块的数量(%b):

st_blocks

在我的系统上,我得到stat -c 'st_size=%s st_blocks=%b' sparse-file ,因为实际的文件系统块大小是4096字节(= 8×512),而这个稀疏文件只需要一个文件系统块。

但是,使用st_size=1048576 st_blocks=8我得到ls -s sparse-file,因为默认的ls块大小是1024字节。如果我跑

4 sparse-file

然后我看到了ls --block-size=512 -s sparse-file ,正如我所料。

答案 1 :(得分:2)

这里的“块”不是真正的文件系统块。它们是方便显示的块。

st_blocks正在使用可能 512字节块。请参阅the POSIX spec

st_blksize是此文件的首选块大小,但不一定是实际的块大小。

BSD ls -s总是使用512字节“块”。例如,OS X默认使用BSD ls。

$ /bin/ls -s index.html 
560 index.html

GNU ls似乎使用1K块,除非用--block-size覆盖。

$ /opt/local/bin/gls -s index.html 
280 index.html

printf("%lld / %d\n", buf.st_blocks, buf.st_blksize);生成560 / 4096。 560“块”是512字节块,但真正的文件系统块是4k。

该文件包含284938个字节的数据......

$ ls -l index.html 
-rw-r--r-- 1 schwern staff 284938 Aug 11  2016 index.html

...但我们可以看到它在磁盘上使用280K或70字节。

enter image description here

请注意,OS X通过使用1000字节表示“千字节”而不是正确的1024字节来进一步混淆问题,这就是为什么它说70个4096 KB块(即286720字节)而不是280 KB的287 KB。之所以这样做是因为硬盘驱动器制造商开始使用1000字节“千字节”来扩大其规模,而Apple厌倦了抱怨“丢失”磁盘空间的客户。

通过制作一个小文件可以看到4K块大小。

enter image description here