Linux stat命令Blocks字段与IO Block字段的理解

原因

在之前了解文件系统的时候,为理解块与扇区的概念,用到了stat命令。

关于这个命令输出的信息的文章有很多,其他字段是没有争议的,但是在一些文章中对BlocksIO Block理解有错误。

结论

先说结论

Blocks字段指的是512字节构成的块的个数,IO Block是指文件系统的块的大小一般为4096字节。

它们关系如下

$$ IO\space Block = Blocks\times 512B $$

网上有很多文章说Blocks字段指的是文件系统中块的个数,这个是错误的。实践是检验真理的唯一标准,下面我们就直接查看Linux的stat命令的源码验证一下。

验证

首先终端执行以下命令,搜索stat所在目录

which stat

得到如下结果

然后再搜索软件所在包

dpkg -S /usr/bin/stat

发现是在coreutils包下

GNU的网站下载这个包

然后解压缩,于src文件夹下和lib文件夹下分别查看stat.c这个源文件发现并没有与这两个字段相关的类型定义,这看似我们寻找失败了。但是经过一段时间摸索,在lib下的stat.c中包含了sys/stat.h头文件,我们想要找的答案很可能就在这里面

利用清华大学镜像源加速,获取glibc,解压后在usr/include目录下终于找到了stat.h头文件

查看内容,果然有一个名为stat的结构体,代码片段如下

struct stat
  {
    unsigned int st_dev;        /* Device.  */
    unsigned int st_ino;        /* File serial number.    */
    unsigned int st_mode;        /* File mode.  */
    unsigned int st_nlink;        /* Link count.  */
    unsigned int st_uid;        /* User ID of the file's owner.    */
    unsigned int st_gid;        /* Group ID of the file's group.*/
    unsigned int st_rdev;        /* Device number, if device.  */
    long int st_size;            /* Size of file, in bytes.  */
    unsigned long int st_atime;        /* Time of last access.  */
    unsigned long int st_mtime;        /* Time of last modification.  */
    unsigned long int st_ctime;        /* Time of last status change.  */
    unsigned int st_blksize;        /* Optimal block size for I/O.  */
#define    _STATBUF_ST_BLKSIZE        /* Tell code we have this member.  */
    int st_blocks;            /* Nr. of 512-byte blocks allocated.  */
    unsigned int st_flags;
    unsigned int st_gen;
  };

找到名st_blocks的结构体成员,右边的注释写着“512-byte blocks”,这显然说明stat命令的Blocks字段含义就是以512字节为单位的个数。

为什么是512?因为早期的机械硬盘扇区大小为512字节,但现在无论SSD还是机械,存储单位都是4096字节的了,正好是512的整数倍。

而IO Block是指文件系统中的块的大小,对应st_blksize成员,相当于8个512字节块(对于512字节扇区的磁盘来讲,在物理上表现为8个连续的扇区),即4096字节。

而这个512字节的块究竟是物理块还是逻辑块?由于现在存储设备的发展,以及不同文档中有不同定义,这些东西的概念十分模糊,所以我并不建议把它理解成一个实际存在的块,而是作为一个基本单位。笔者认为在学习文件系统的时候只需要知道,文件系统中的块相当于8个这样的连续的基本单位组成就足够了。

其他

通过阅读代码可以发现在Linux中,stat命令所说的Size字段指的是文本大小,而不是文件实际占用大小。

Size字段对应stat结构体st_size成员,该字段数值并不等于IO Block*Blocks(而Windows中是这样)。

文件的实际占用空间应该为 文件系统的块大小*文件文件系统块的个数

$$ TrueSize = FileBlock \times FileBlockNum $$

最后修改:2022 年 08 月 10 日
如果觉得我的文章对你有用,请随意赞赏