只有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級別的小文件,就等着去財務處領錢吧!

相關文章
相關標籤/搜索