追蹤文件I/O背后涉及的相關(guān)知識(shí)

難得擁有大塊的空閑時(shí)間挟秤,所以近期對(duì)操作系統(tǒng)的部分核心知識(shí)進(jìn)行了系統(tǒng)的學(xué)習(xí)以及總結(jié)。借助平臺(tái)將一些收獲進(jìn)行整理并分享給讀者,希望文章中的內(nèi)容能帶來一些收獲追迟。

本文深入文件讀寫底層,引出I/O行為背后涉及到的頁高速緩存骚腥、內(nèi)存與塊設(shè)備直接的交互敦间、Mmap等知識(shí)點(diǎn)。


我們知道束铭,當(dāng)提到文件時(shí)有兩個(gè)問題需要我們注意:第一是由于存儲(chǔ)塊設(shè)備與內(nèi)存直接的速度不匹配從而導(dǎo)致的性能問題廓块、第二個(gè)是多個(gè)進(jìn)程有時(shí)需要讀取同一個(gè)文件內(nèi)容,即一旦數(shù)據(jù)被訪問契沫,就很有可能在短時(shí)間被二次訪問带猴。

于是便引出了我們今天要講述的主角:頁緩存(Page Cache)。

下面我們來看一個(gè)文件讀取的例子:

假設(shè)系統(tǒng)中現(xiàn)在存在一個(gè)名為render的進(jìn)程懈万,該進(jìn)程打開了文件scene.dat拴清,并且每次讀取其中的512B(一個(gè)扇區(qū)的大小),將讀取的文件數(shù)據(jù)放入到堆分配的塊中(每個(gè)進(jìn)程自己的地址空間對(duì)應(yīng)的物理內(nèi)存)会通。

image

1.進(jìn)程調(diào)用庫函數(shù)read()向內(nèi)核發(fā)起讀文件的請(qǐng)求口予,希望讀取scene.data的512B內(nèi)容;

2.這里我們假設(shè)cache中并沒有所需要讀取的數(shù)據(jù)所以需要向Disk中尋找數(shù)據(jù)涕侈,于是內(nèi)核通過檢查進(jìn)程的文件描述符定位到虛擬文件系統(tǒng)已經(jīng)打開的文件列表項(xiàng)沪停,調(diào)用該文件系統(tǒng)對(duì)VFS的read()調(diào)用提供的接口;

3.通過文件表項(xiàng)鏈接到目錄項(xiàng)模塊裳涛,根據(jù)傳入的文件路徑在目錄項(xiàng)中檢索木张,找到該文件的inode;

4.根據(jù)inode找到文件调违,通過文件內(nèi)容偏移量計(jì)算出要讀取的頁窟哺,將頁中對(duì)應(yīng)的512B數(shù)據(jù)先讀取到page cache處;

5.最后再通過該inode的i_mapping指針找到對(duì)應(yīng)的address_space頁緩存樹---基樹技肩,查找對(duì)應(yīng)的頁緩存節(jié)點(diǎn)且轨;

簡單來說:

  • (1)如果頁緩存節(jié)點(diǎn)命中,那么直接返回文件內(nèi)容虚婿;

  • (2)如果頁緩存缺失旋奢,那么產(chǎn)生一個(gè)缺頁異常,首先創(chuàng)建一個(gè)新的空的物理頁框然痊,通過該inode找到文件中該頁的磁盤地址至朗,讀取相應(yīng)的頁填充該頁緩存(DMA的方式將數(shù)據(jù)讀取到頁緩存),更新頁表項(xiàng)剧浸,最后再從頁緩存中讀锹引;

所有的文件內(nèi)容的讀却V印(無論一開始是命中頁緩存還是沒有命中頁緩存)最終都是直接來源于頁緩存。當(dāng)將數(shù)據(jù)從磁盤復(fù)制到頁緩存之后嫌变,還要將頁緩存的數(shù)據(jù)通過CPU復(fù)制到read調(diào)用提供的緩沖區(qū)中吨艇,這就是普通文件IO需要的兩次復(fù)制數(shù)據(jù)復(fù)制過程。其中第一次是通過DMA的方式將數(shù)據(jù)從磁盤復(fù)制到頁緩存中腾啥,本次過程只需要CPU在一開始的時(shí)候讓出總線东涡、結(jié)束之后處理DMA中斷即可,中間不需要CPU的直接干預(yù)倘待,CPU可以去做別的事情疮跑;第二次是將數(shù)據(jù)從頁緩存復(fù)制到進(jìn)程自己的的地址空間對(duì)應(yīng)的物理內(nèi)存中,這個(gè)過程中需要CPU的全程干預(yù)凸舵,浪費(fèi)CPU的時(shí)間和額外的物理內(nèi)存空間祖娘。

此時(shí)對(duì)于render進(jìn)程來說,其堆會(huì)指向Page Frames的三個(gè)存放數(shù)據(jù)的區(qū)域贞间,從而完成數(shù)據(jù)的讀取贿条。

image

在上面的內(nèi)容中我們提到了——address_space與基樹(radix tree)

Address_space對(duì)象

在Page Cache中存在多個(gè)不連續(xù)的物理磁盤塊(512B,而頁大小為4KB)增热,所以如何通過頁來定位我們所需要的數(shù)據(jù)是一個(gè)很重要并且很困難的事情整以。(如果能用設(shè)備號(hào)+塊號(hào)來定位是最好的,但是頁與塊大小不匹配峻仇,所以不太行)

于是這里就需要我們引入address_space對(duì)象來幫助我們:

struct address_space {

每一個(gè)所有者(可以理解為一個(gè)具體的文件公黑,一個(gè)inode指向的文件)對(duì)應(yīng)著一個(gè)address_space對(duì)象,頁高速緩存的多個(gè)頁可能屬于一個(gè)所有者摄咆,從而可以鏈接到一個(gè)address_space對(duì)象凡蚜。那么一個(gè)頁(page)怎么和一個(gè)address_space產(chǎn)生關(guān)聯(lián)的呢?

page中有兩個(gè)字段:mapping和index吭从。其中mapping指向該頁所有者的address_mapping(內(nèi)存inode結(jié)構(gòu)有一個(gè)i_mapping指向?qū)?yīng)address_space對(duì)象)朝蜘,index字段表示所有者地址空間中以頁大小為單位的偏移量。用這兩個(gè)字段就能在頁高速緩存中查找頁涩金。(這里注意一點(diǎn)谱醇,一個(gè)頁中所包含的磁盤塊在物理上不一定是相鄰的)——即調(diào)用函數(shù) find_get_page(mapping, index) 在page cache中查找所需數(shù)據(jù)。

而address_space中頁表的總數(shù)由nrpages描述步做。

address_space中有一個(gè)host字段副渴,該字段指向其所屬的inode,也就是address_space中的host字段 與 對(duì)應(yīng)inode中的 i_data字段形成互相指向的關(guān)系全度。

基樹(Radix樹)

由address_space的知識(shí)中我們知道煮剧,若需要在page cache中找到對(duì)應(yīng)數(shù)據(jù)需要根據(jù)其中的radix_tree_root來找到基樹的root,從而能快速搜索到所需要的值的位置。而在緩存中要求這個(gè)查詢速度需要非趁阒眩快佑颇,如果開銷太大會(huì)抵消緩存的好處。

(Radix樹就類似于傳統(tǒng)的二叉樹菇篡,如下圖)

不過這里就不介紹過多漩符,后期會(huì)專門出一篇Radix樹的詳細(xì)內(nèi)容一喘。

image

對(duì)于寫操作來說驱还,當(dāng)一個(gè)進(jìn)程調(diào)用write系統(tǒng)調(diào)用的時(shí)候,對(duì)于文件的更新僅僅是被寫到了文件的頁緩存中凸克,相應(yīng)的頁被標(biāo)記為dirty议蟆。

在address_space中查詢對(duì)應(yīng)頁的頁緩存是否存在:如果頁緩存命中,直接把文件內(nèi)容修改寫在頁緩存的頁中萎战。寫文件就結(jié)束了咐容。這時(shí)候文件修改位于頁緩存,并沒有寫回到磁盤文件中去蚂维;

如果頁緩存缺失戳粒,那么產(chǎn)生一個(gè)頁缺失異常,創(chuàng)建一個(gè)頁緩存頁虫啥,同時(shí)通過inode找到該文件頁的磁盤地址蔚约,讀取相應(yīng)的頁填充頁緩存。

由于緩存涂籽,寫操作實(shí)際上會(huì)被延遲苹祟。而那些在頁緩存中修改過的數(shù)據(jù)叫做臟數(shù)據(jù),而這些數(shù)據(jù)必須要被寫回磁盤评雌,那什么時(shí)候?qū)懙模?/p>

1 當(dāng)空閑內(nèi)存<閾值树枫;

2 臟頁停留時(shí)間>一定閾值時(shí);

這里就需要調(diào)用Flusher線程進(jìn)行刷新操作了景东;而操作系統(tǒng)會(huì)定時(shí)調(diào)用這個(gè)線程砂轻。

Mmap

在一次文件讀取的過程中,必須將文件的內(nèi)容從頁緩存拷貝到用戶的空間斤吐。這個(gè)過程和缺頁異常(通過DMA調(diào)入需要的頁)不一樣搔涝,這個(gè)拷貝過程需要通過CPU進(jìn)行,因此浪費(fèi)了CPU的時(shí)間曲初。另一個(gè)弊端就是浪費(fèi)了物理內(nèi)存体谒,因?yàn)樾枰獮橥瑯拥臄?shù)據(jù)在內(nèi)存中維護(hù)兩個(gè)副本,如下圖render進(jìn)程的heap所對(duì)應(yīng)的堆中的數(shù)據(jù)和頁緩存中的數(shù)據(jù)存在重復(fù)臼婆,并且如果系統(tǒng)中有多個(gè)這樣的進(jìn)程的話抒痒,那么需要為每個(gè)進(jìn)程維護(hù)同樣的一份數(shù)據(jù)副本,嚴(yán)重浪費(fèi)了CPU的時(shí)間和物理內(nèi)存空間颁褂。

image

于是此處需要Mmap方案故响。通過mmap傀广,進(jìn)程不但可以直接操作文件對(duì)應(yīng)的物理內(nèi)存,減少從內(nèi)核空間到用戶空間的數(shù)據(jù)復(fù)制過程彩届,同時(shí)可以和別的進(jìn)程共享頁緩存中的數(shù)據(jù)伪冰,達(dá)到節(jié)約內(nèi)存的作用。(如下圖中就存在多余的數(shù)據(jù)樟蠕,浪費(fèi)了空間)

image

對(duì)于寫操作來說贮聂,普通的IO操作需要將寫的數(shù)據(jù)從自己的進(jìn)程地址空間復(fù)制到頁緩存中,完成對(duì)頁緩存的寫入寨辩;但是mmap通過虛擬地址可以直接完成對(duì)頁緩存的寫入吓懈,減少了從用戶空間到頁緩存的復(fù)制。

普通文件IO中所有的文件內(nèi)容的讀让夷(無論一開始是命中頁緩存還是沒有命中頁緩存)最終都是直接來源于頁緩存耻警。當(dāng)將數(shù)據(jù)通過缺頁中斷從磁盤復(fù)制到頁緩存之后,還要將頁緩沖的數(shù)據(jù)通過CPU復(fù)制到read調(diào)用提供的緩沖區(qū)中甸怕。這樣甘穿,必須通過兩次數(shù)據(jù)拷貝過程,才能完成用戶進(jìn)程對(duì)文件內(nèi)容的獲取任務(wù)梢杭。寫操作也是一樣的温兼,待寫入的buffer在用戶空間,必須將其先拷貝到內(nèi)核空間對(duì)應(yīng)的主存中式曲,再寫回到磁盤中妨托,也是需要兩次數(shù)據(jù)拷貝。mmap的使用減少了數(shù)據(jù)從用戶空間到頁緩存的復(fù)制過程吝羞,提高了IO的效率兰伤,尤其是對(duì)于大文件而言;對(duì)于比較小的文件而言钧排,由于mmap執(zhí)行了更多的內(nèi)核操作敦腔,因此其效率可能比普通的文件IO更差。

?

mmap和常規(guī)文件操作的區(qū)別

我們首先簡單的回顧一下常規(guī)文件系統(tǒng)操作(調(diào)用read/fread等類函數(shù))中恨溜,函數(shù)的調(diào)用過程:

  • 1符衔、進(jìn)程發(fā)起讀文件請(qǐng)求。

  • 2糟袁、內(nèi)核通過查找進(jìn)程文件符表判族,定位到內(nèi)核已打開文件集上的文件信息,從而找到此文件的inode项戴。

  • 3形帮、inode在address_space上查找要請(qǐng)求的文件頁是否已經(jīng)緩存在頁緩存中。如果存在,則直接返回文件頁的內(nèi)容辩撑。

  • 4界斜、如果不存在,則通過inode定位到文件磁盤地址合冀,將數(shù)據(jù)從磁盤復(fù)制到頁緩存各薇。之后再次發(fā)起讀頁面過程,進(jìn)而將頁緩存中的數(shù)據(jù)發(fā)給用戶進(jìn)程君躺。

總結(jié)來說峭判,常規(guī)文件操作為了提高讀寫效率和保護(hù)磁盤,使用了頁緩存機(jī)制晰洒。這樣造成讀文件時(shí)需要先將文件頁從磁盤拷貝到頁緩存中朝抖,由于頁緩存處在內(nèi)核空間,不能被用戶進(jìn)程直接尋址谍珊,所以還需要將頁緩存中數(shù)據(jù)頁再次拷貝到內(nèi)存對(duì)應(yīng)的用戶空間中。這樣急侥,通過了兩次數(shù)據(jù)拷貝過程砌滞,才能完成進(jìn)程對(duì)文件內(nèi)容的獲取任務(wù)。寫操作也是一樣坏怪,待寫入的buffer在內(nèi)核空間不能直接訪問贝润,必須要先拷貝至內(nèi)核空間對(duì)應(yīng)的主存,再寫回磁盤中(延遲寫回)铝宵,也是需要兩次數(shù)據(jù)拷貝打掘。

而使用mmap操作文件中,創(chuàng)建新的虛擬內(nèi)存區(qū)域和建立文件磁盤地址和虛擬內(nèi)存區(qū)域映射這兩步鹏秋,沒有任何文件拷貝操作尊蚁。而之后訪問數(shù)據(jù)時(shí)發(fā)現(xiàn)內(nèi)存中并無數(shù)據(jù)而發(fā)起的缺頁異常過程,可以通過已經(jīng)建立好的映射關(guān)系侣夷,只使用一次數(shù)據(jù)拷貝横朋,就從磁盤中將數(shù)據(jù)傳入內(nèi)存的用戶空間中,供進(jìn)程使用百拓。

總而言之琴锭,常規(guī)文件操作需要從磁盤到頁緩存再到用戶主存的兩次數(shù)據(jù)拷貝。而mmap操控文件衙传,只需要從磁盤到用戶主存的一次數(shù)據(jù)拷貝過程决帖。說白了,mmap的關(guān)鍵點(diǎn)是實(shí)現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)直接交互而省去了空間不同數(shù)據(jù)不同的繁瑣過程蓖捶。因此mmap效率更高地回。

文章在閱讀操作系統(tǒng)相關(guān)數(shù)據(jù)的基礎(chǔ)上還參考了一些blog:

https://blog.csdn.net/icycode/article/details/80211207#flush%E5%86%85%E6%A0%B8%E7%BA%BF%E7%A8%8B

https://manybutfinite.com/post/page-cache-the-affair-between-memory-and-files/

https://blog.csdn.net/gdj0001/article/details/80136364


內(nèi)核這個(gè)東西,真的有點(diǎn)復(fù)雜。學(xué)習(xí)與總結(jié)都是需要慢慢進(jìn)行落君。一天過去了穿香,我也就學(xué)了這點(diǎn)東西。效率還是要提高绎速。歡迎批評(píng)指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皮获,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纹冤,更是在濱河造成了極大的恐慌洒宝,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萌京,死亡現(xiàn)場(chǎng)離奇詭異雁歌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)知残,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門靠瞎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人求妹,你說我怎么就攤上這事乏盐。” “怎么了制恍?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵父能,是天一觀的道長。 經(jīng)常有香客問我净神,道長何吝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任鹃唯,我火速辦了婚禮爱榕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俯渤。我一直安慰自己呆细,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布八匠。 她就那樣靜靜地躺著絮爷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梨树。 梳的紋絲不亂的頭發(fā)上坑夯,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音抡四,去河邊找鬼柜蜈。 笑死仗谆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淑履。 我是一名探鬼主播隶垮,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼秘噪!你這毒婦竟也來了狸吞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤指煎,失蹤者是張志新(化名)和其女友劉穎蹋偏,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體至壤,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡威始,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了像街。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黎棠。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宅广,靈堂內(nèi)的尸體忽然破棺而出葫掉,到底是詐尸還是另有隱情,我是刑警寧澤跟狱,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站户魏,受9級(jí)特大地震影響驶臊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叼丑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一关翎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸠信,春花似錦纵寝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绰垂,卻和暖如春室奏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劲装。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工胧沫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昌简,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓绒怨,卻偏偏與公主長得像纯赎,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • 一.管道機(jī)制(pipe) 1.Linux的fork操作 在計(jì)算機(jī)領(lǐng)域中,尤其是Unix及類Unix系統(tǒng)操作系統(tǒng)中拷泽,...
    Geeks_Liu閱讀 3,680評(píng)論 1 9
  • 目錄 系統(tǒng)調(diào)用 虛擬文件系統(tǒng) I/O 緩沖區(qū) Page Cache Address Space 文件讀寫基本流程 ...
    boyiis閱讀 900評(píng)論 1 5
  • mmap基礎(chǔ)概念 mmap是一種內(nèi)存映射文件的方法趴俘,即將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤地址...
    dequal閱讀 1,174評(píng)論 0 1
  • Linux進(jìn)程通信實(shí)現(xiàn)機(jī)制有很多镇眷,也有各自優(yōu)缺點(diǎn)和適用場(chǎng)景,關(guān)于她們之間的對(duì)比,等各種通信機(jī)制一一介紹后音同,再來一個(gè)...
    batbattle閱讀 4,063評(píng)論 3 13
  • 【導(dǎo)讀】 銷售極富創(chuàng)造性锅锨,是一門深?yuàn)W的學(xué)問叽赊,它是綜合了市場(chǎng)學(xué)、心理學(xué)必搞、口才學(xué)必指、表演學(xué)等知識(shí)的一種藝術(shù)工作。所以恕洲,使...
    錢心流閱讀 283評(píng)論 0 4