在前文《新建一個空文件佔用多少磁盤空間?》中咱們瞭解到了一個空文件的磁盤開銷。 今天咱們再思考另一個問題,假如咱們給文件裏只寫入1個字節,那麼這個文件實際的磁盤佔用多大,難道真的是1個字節嗎?
node
和前文同樣,先不談原理,直接動手操做。
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級別的小文件,就等着去財務處領錢吧!