文件過多時(shí)ls命令為什么會(huì)卡淄璞摺叠必?

不知道你有沒有遇到過當(dāng)一個(gè)文件夾下文件特別多,在下面執(zhí)行ls命令的時(shí)候要等好長時(shí)間才能展現(xiàn)出來的問題妹窖?如果有纬朝,你有想過這是為什么嗎,我們?cè)撊绾谓鉀Q?
要想深入理解這個(gè)的問題產(chǎn)生的原因骄呼,我們就需要從文件夾占用的磁盤空間開始討論了共苛。

inode消耗驗(yàn)證

在《新建一個(gè)空文件占用多少磁盤空間?》中我提到了每一個(gè)文件會(huì)消耗其所在文件夾中的一點(diǎn)空間蜓萄。文件夾呢隅茎,其實(shí)也一樣會(huì)消耗inode的。 我們先看一下當(dāng)前inode的占用情況

# df -i  
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
......
/dev/sdb1            2147361984 12785020 2134576964    1% /search

再創(chuàng)建一個(gè)空文件夾

# mkdir temp
# df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
......
/dev/sdb1            2147361984 12785021 2134576963    1% /search

通過IUsed可以看到嫉沽,和空文件一樣辟犀,空的文件夾也會(huì)消耗掉一個(gè)inode。不過這個(gè)很小绸硕,我的機(jī)器上才是256字節(jié)而已堂竟,應(yīng)當(dāng)不是造成ls命令卡主的元兇魂毁。

block消耗驗(yàn)證

文件夾的名字存在哪兒了呢?嗯跃捣,和《新建一個(gè)空文件占用多少磁盤空間漱牵?》里的文件類似,會(huì)消耗一個(gè)ext4_dir_entry_2(今天用ext4舉例疚漆,它在linux源碼的fs/ext4/ex4.h文件里定義),放到其父目錄的block里了酣胀。根據(jù)這個(gè),相信你也很快能想到娶聘,如果它自己節(jié)點(diǎn)下創(chuàng)建一堆文件的話闻镶,就會(huì)占用它自己的block。我們來動(dòng)手驗(yàn)證一下:

# mkdir test
# cd test  
# du -h
4.0K    .

這里的4KB就表示消耗掉了一個(gè)block丸升。 空文件不消耗block铆农,空目錄為啥一開始就消耗block了呢,那是因?yàn)槠浔仨毮J(rèn)帶兩個(gè)目錄項(xiàng)"."和".."狡耻。另外這個(gè)4K在你的機(jī)器上不一定是這么大墩剖,它其實(shí)是一個(gè)block size,在你格式化的時(shí)候決定的夷狰。

我們?cè)傩陆▋蓚€(gè)空的文件岭皂,再查看一下:

# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# du -h
4.0K    .

貌似,沒有什么變化沼头。這是因?yàn)?/p>

  • 第一爷绘、新的空文件不占用block,所以這里顯示的仍然是目錄占用的block进倍。
  • 第二土至、之前文件夾創(chuàng)建時(shí)候分配的4KB里面空閑空間還有,夠放的下這兩個(gè)文件項(xiàng)

那么我再多創(chuàng)建一些試試猾昆,動(dòng)用腳本創(chuàng)建100個(gè)文件名長度為32Byte的空文件陶因。

#!/bin/bash
for((i=1;i<=100;i++));
do
        file="tempDir/"$(echo $i|awk '{printf("%032d",$0)}')
        echo $file
        touch $file
done
# du -h
12K    .

哈哈,這時(shí)我們發(fā)現(xiàn)目錄占用的磁盤空間變大了垂蜗,成了3個(gè)Block了坑赡。當(dāng)我們創(chuàng)建到10000個(gè)文件的時(shí)候,

# du -h
548K     .

在每一個(gè)ext4_dir_entry_2里都除了文件名以外么抗,還記錄著inode號(hào)等信息,詳細(xì)定義如下:

struct ext4_dir_entry_2 {
        __le32  inode;                  /* Inode number */
        __le16  rec_len;                /* Directory entry length */
        __u8    name_len;               /* Name length */
        __u8    file_type;
        char    name[EXT4_NAME_LEN];    /* File name */
};

我們計(jì)算一下亚铁,平均每個(gè)文件占用的空間=548K/10000=54字節(jié)蝇刀。也就是說,比我們的文件名32字節(jié)大一點(diǎn)點(diǎn)徘溢,基本對(duì)上了吞琐。 這里我們也領(lǐng)會(huì)到一個(gè)事實(shí)捆探,文件名越長,在其父目錄中消耗的空間也會(huì)越大站粟。

本文結(jié)論

一個(gè)文件夾當(dāng)然也是要消耗磁盤空間的黍图。

  • 首先要消耗掉一個(gè)inode,我的機(jī)器上它是256字節(jié)
  • 需要消耗其父目錄下的一個(gè)目錄項(xiàng)ext4_dir_entry_2奴烙,保存自己inode號(hào)助被,目錄名。
  • 其下面如果創(chuàng)建文件夾或者文件的話切诀,它就需要在自己的block里ext4_dir_entry_2數(shù)組

目錄下的文件/子目錄越多揩环,目錄就需要申請(qǐng)?jiān)蕉嗟腷lock。另外ext4_dir_entry_2大小不是固定的幅虑,文件名/子目錄名越長丰滑,單個(gè)目錄項(xiàng)消耗的空間也就越大。

對(duì)于開篇的問題倒庵,我想你現(xiàn)在應(yīng)該明白為什么了,問題出在文件夾的block身上褒墨。
這就是當(dāng)你的文件夾下面文件特別多,尤其是文件名也比較長的時(shí)候擎宝,它會(huì)消耗掉非常多的block郁妈。當(dāng)你遍歷文件夾的時(shí)候,如果Page Cache中沒有命中你要訪問的block认臊,就會(huì)穿透到磁盤上進(jìn)行實(shí)際的IO圃庭。在你的角度來看,就是你執(zhí)行完ls后失晴,卡住了剧腻。

那么你肯定會(huì)問,我確實(shí)要保存許許多多的文件涂屁,我該怎么辦? 其實(shí)也很簡單书在,多創(chuàng)建一些文件夾就好了,一個(gè)目錄下別存太多拆又,就不會(huì)有這個(gè)問題了儒旬。工程實(shí)踐中,一般的做法就是通過一級(jí)甚至是二級(jí)hash把文件散列到多個(gè)目錄中帖族,把單目錄文件數(shù)量控制在十萬或萬以下栈源。

ext的bug

貌似今天的實(shí)踐應(yīng)該結(jié)束了,現(xiàn)在讓我們把剛剛創(chuàng)建的文件全部刪掉竖般,再看一下甚垦。

# rm -f *
# du -h
72K     .

等等,什么情況?文件夾下的文件都已經(jīng)刪了艰亮,該文件夾為什么還占用72K的磁盤空間闭翩?
這個(gè)疑惑也伴隨了我很長時(shí)間,后來才算是解惑迄埃。問題關(guān)鍵在于ext4_dir_entry_2中的rec_len疗韵。這個(gè)變量存儲(chǔ)了當(dāng)前整個(gè)ext4_dir_entry_2對(duì)象的長度,這樣操作系統(tǒng)在遍歷文件夾的時(shí)候侄非,就可以通過當(dāng)前的指針蕉汪,加上這個(gè)長度就可以找到文件夾中下一個(gè)文件的dir_entry了。這樣的優(yōu)勢(shì)是遍歷起來非常方便彩库,有點(diǎn)像是一個(gè)鏈表肤无,一個(gè)一個(gè)穿起來的。
但是骇钦,如果要?jiǎng)h除一個(gè)文件的話宛渐,就有點(diǎn)小麻煩了,當(dāng)前文件結(jié)構(gòu)體變量不能直接刪眯搭,否則鏈表就斷了窥翩。
Linux的做法是在刪除文件的時(shí)候,在其目錄中只是把inode設(shè)置為0就拉倒鳞仙,并沒有回收整個(gè)ext4_dir_entry_2對(duì)象寇蚊。其實(shí)和大家做工程的時(shí)候經(jīng)常用到的假刪除是一個(gè)道理。現(xiàn)在的xfs文件系統(tǒng)好像已經(jīng)沒有這個(gè)小問題了棍好,但具體咋解決的仗岸,暫時(shí)沒有深入研究,如果你有答案借笙,歡迎留言扒怖!

歡迎搜索微信公眾號(hào):開發(fā)內(nèi)功修煉

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市业稼,隨后出現(xiàn)的幾起案子盗痒,更是在濱河造成了極大的恐慌,老刑警劉巖低散,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俯邓,死亡現(xiàn)場離奇詭異,居然都是意外死亡熔号,警方通過查閱死者的電腦和手機(jī)稽鞭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來引镊,“玉大人朦蕴,你說我怎么就攤上這事吃嘿。” “怎么了梦重?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亮瓷。 經(jīng)常有香客問我琴拧,道長,這世上最難降的妖魔是什么嘱支? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任蚓胸,我火速辦了婚禮,結(jié)果婚禮上除师,老公的妹妹穿的比我還像新娘沛膳。我一直安慰自己,他們只是感情好汛聚,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布锹安。 她就那樣靜靜地躺著,像睡著了一般倚舀。 火紅的嫁衣襯著肌膚如雪叹哭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天痕貌,我揣著相機(jī)與錄音风罩,去河邊找鬼。 笑死舵稠,一個(gè)胖子當(dāng)著我的面吹牛超升,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哺徊,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼室琢,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了唉工?” 一聲冷哼從身側(cè)響起研乒,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淋硝,沒想到半個(gè)月后雹熬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谣膳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年竿报,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片继谚。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烈菌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芽世,我是刑警寧澤挚赊,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站济瓢,受9級(jí)特大地震影響荠割,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旺矾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一蔑鹦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧箕宙,春花似錦嚎朽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雕崩,卻和暖如春魁索,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盼铁。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工粗蔚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饶火。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓鹏控,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肤寝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子当辐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一個(gè)基本的計(jì)算機(jī)系統(tǒng)由“硬件”和“軟件”組成,一臺(tái)Linux設(shè)備鲤看,主要的組成如下圖所示: 一般情況下缘揪,我們所說的L...
    時(shí)待吾閱讀 1,632評(píng)論 0 16
  • 1.文件系統(tǒng)特性 磁盤分區(qū)后還需要進(jìn)行格式化后操作系統(tǒng)才能使用這個(gè)文件系統(tǒng),為什么要格式化义桂? 因?yàn)槊總€(gè)操作系統(tǒng)所設(shè)...
    過來摸摸頭丶閱讀 354評(píng)論 0 0
  • 初探 文件系統(tǒng)的功能以塊為單位的存儲(chǔ)組織形式要有索引, 方便查找熱點(diǎn)文件應(yīng)該有緩存可以以文件夾形式組織, 方便管理...
    西山薄涼閱讀 439評(píng)論 0 0
  • 真是一個(gè)無情的搬運(yùn)工 前言 本文同樣更新在私人公眾號(hào)上找筝,在此推廣一下歡迎大家關(guān)注: 公眾號(hào)會(huì)定期更新一些計(jì)算機(jī)系統(tǒng)...
    CPinging閱讀 428評(píng)論 0 4
  • Linux系統(tǒng)一般有4個(gè)主要部分:內(nèi)核、shell慷吊、文件系統(tǒng)和應(yīng)用程序袖裕。 內(nèi)核、shell和文件系統(tǒng)一起形成了基本...
    請(qǐng)愛護(hù)小動(dòng)物閱讀 2,546評(píng)論 0 22