只有1个字节的文件实际占用多少磁盘空间

图片

在前文《新建一个空文件占用多少磁盘空间?》中咱们了解到了一个空文件的磁盘开销。 今天咱们再思考另一个问题,假如咱们给文件里只写入1个字节,那么这个文件实际的磁盘占用多大,难道真的是1个字节吗?
node

1查看1个字节的文件

和前文同样,先不谈原理,直接动手操做。
linux

# mkdir tempDir
# cd tempDir
# du -h
0    .
# touch test
# du -h
0    .

在一个目录中建立了一个空的文件之后,经过du命令看到的该文件夹的占用空间并无发生变化。这符合咱们以前的认识,由于空文件只占用inode。好,那让咱们修改文件,添加一个字母数组

echo "a" > test
# du -h
4.0K    .

保存后再次查看该目录的空间占用。咱们发现由原来的0增长到了4K。 因此说,文件里的内容不论多小,哪怕是一个字节,其实操做系统也会给你分配4K的。哦,固然了还得再算前文中说到的inode和文件夹数据结构中存储的文件名等所用的空间。 因此,不要在你的系统里维护一大堆的碎文件。文件再小,占用磁盘其实一点都很多!缓存

注意个人实验环境是在ext文件系统下进行的。若是是xfs可能表现会有些许出入。

2继续讨论这个4K数据结构

再把linux源代码文件fs/ext2/ext2.h里关于inode的定义翻出来,咱们找到结构体中定义的指向数据节点用的block数组:
app

struct ext2_inode {
   ......
   __le32  i_block[EXT2_N_BLOCKS]; # 指向存储文件数据的块的数组
   ......

当文件没有数据须要存储的时候,这个数组都是空值。而当咱们写入了1个字节之后,文件系统就须要申请block去存储了,申请完后,指针放在这个数组里。哪怕文件内容只有一个字节,仍然会分配一个整的Block,由于这是文件系统的最小工做单位。那么这个block大小是多大呢,ext下能够经过dumpe2fs查看。分布式

#dumpe2fs -h /dev/mapper/vgroot-lvroot
......
Block size:               4096

在个人机器上,一个Block是4KB。ide

3文件内容大了怎么办?性能

不知道你留意没,inode中定义的block数组大小呢,只有EXT2_N_BLOCKS个。咱们再查看一下这个常量的定义,发现它是15,相关内核中定义以下:
spa

#define EXT2_NDIR_BLOCKS        12
#define EXT2_IND_BLOCK         EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK        (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK        (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS              (EXT2_TIND_BLOCK + 1)

就按4K的block size来看,15个block只够存的下15*4=60K的文件。 这个文件大小相信你必定不满意,你存一个avi大片都得上G了。那Linux是怎么实现大文件存储的呢?嗯,其实上面宏的定义过程已经告诉你了,就是只有12个数组直接存block指针,其他的用来作间接索引(EXT2_IND_BLOCK),二级间接索引(EXT2_DIND_BLOCK)和三级索引(EXT2_TIND_BLOCK)。

图片图1 inode中的直接与间接索引

这样,一个文件能够使用的空间就指数倍的扩展了。 文件小的时候,都用直接索引,磁盘IO少,性能好。文件大的时候,访问一个block可能得先进行三次的IO,性能略慢,不过有OS层面的页缓存、目录项缓存的加持,也还好。

4结论

文件系统是按照inode+block来组织的,因此无论你的文件多小,哪怕只有一个字节,在数据上都会消耗掉整整一个块(固然还得算上inode等开销)。这个块大小能够经过dumpe2fs等命令来查看。若是想改变这个块大小怎么办?对不起,只能从新格式化。

再扯的远一点,全部的文件系统理念都是按照块来分配的,包括分布式文件系统,例如HDFS。因为HDFS应用场景是各类GB、TB甚至是PB级别的数据处理。因此为了下降block的管理成本,它的block size设置的很是大。在比较新的版本里,一个block直接就是128M,你没看错,单位是M。 因此若是你没有block的概念,每天在HDFS上都保存一堆KB级别的小文件,就等着去财务处领钱吧!

相关文章
相关标签/搜索