Linux 虛擬文件系統(tǒng)(VFS)分析

我們知道在Linux系統(tǒng)中一切皆文件,如果說文件系統(tǒng)是Linux系統(tǒng)的基石一點(diǎn)也不過分暖眼。在Linux系統(tǒng)中基本上把其中的所有內(nèi)容都看作文件,除了我們普通意義理解的文件之外,目錄瘾杭、字符設(shè)備、塊設(shè)備哪亿、 套接字粥烁、進(jìn)程、線程蝇棉、管道等都被視為是一個(gè)“文件”讨阻。例如對(duì)于塊設(shè)備,我們通過fdisk -l顯示塊設(shè)備列表篡殷,其實(shí)塊設(shè)備可以理解為在文件夾/dev下面的文件钝吮。只不過這些文件是特殊的文件。

root@vmhost:~# ls /dev/ -alh |grep sd
brw-rw---- 1 root disk 8, 0 Dec 31 09:38 sda
brw-rw---- 1 root disk 8, 16 Dec 31 09:38 sdb
brw-rw---- 1 root disk 8, 32 Dec 31 09:38 sdc

如上面代碼所示板辽,每個(gè)塊設(shè)備的前面有一個(gè)字符串brw-rw----奇瘦,這個(gè)用于描述文件的屬性,其中b字符表示這個(gè)文件是一個(gè)塊設(shè)備劲弦,如果是d字符則表示是一個(gè)文件夾耳标。同樣口四,還有其它類型的設(shè)備也是一文件的形式進(jìn)行表示的麸俘。那么Linux的文件系統(tǒng)要支持如此之多類型的文件是怎么做到的呢理肺?那就是通過虛擬文件系統(tǒng)(Virtual File System簡(jiǎn)稱VFS)踱蛀。


虛擬文件系統(tǒng)總圖

VFS是一個(gè)抽象層阱飘,其向上提供了統(tǒng)一的文件訪問接口差导,而向下則兼容了各種不同的文件系統(tǒng)忆谓。不僅僅是諸如Ext2孙技、Ext4夜赵、XFS和Btrfs等常規(guī)意義上的文件系統(tǒng)明棍,還包括偽文件系統(tǒng)和設(shè)備等等內(nèi)容。由圖1可以看出寇僧,虛擬文件系統(tǒng)位于應(yīng)用與具體文件系統(tǒng)之間摊腋,其主要起適配的作用。對(duì)于應(yīng)用程序來說嘁傀,其訪問的接口是完全一致的(例如open兴蒸、read和write等),并不需要關(guān)系底層的文件系統(tǒng)細(xì)節(jié)细办。也就是一個(gè)應(yīng)用可以對(duì)一個(gè)文件進(jìn)行任何的讀寫橙凳,不用關(guān)心文件系統(tǒng)的具體實(shí)現(xiàn)。另外,VFS實(shí)現(xiàn)了一部分公共的功能岛啸,例如頁緩存和inode緩存等钓觉,從而避免多個(gè)文件系統(tǒng)重復(fù)實(shí)現(xiàn)的問題。

VFS的存在可以讓Linux操作系統(tǒng)實(shí)現(xiàn)非常復(fù)雜的文件系統(tǒng)關(guān)聯(lián)關(guān)系坚踩。如圖2所示荡灾,該系統(tǒng)根文件系統(tǒng)是Ext3文件系統(tǒng),而在其/mnt目錄下面又分別掛載了Ext4文件系統(tǒng)和XFS文件系統(tǒng)瞬铸。最后形成了一個(gè)由多個(gè)文件系統(tǒng)組成的文件系統(tǒng)樹批幌。


文件系統(tǒng)目錄樹

從VFS到具體文件系統(tǒng)

VFS是一個(gè)抽象層,VFS建立了應(yīng)用程序與具體文件系統(tǒng)的聯(lián)系赴捞,其提供了統(tǒng)一的訪問接口實(shí)現(xiàn)對(duì)具體文件系統(tǒng)的訪問(例如Ext2文件系統(tǒng))逼裆。那么兩者是怎么關(guān)聯(lián)起來的呢?這里涉及如下幾個(gè)處理流程:

  • 掛載赦政,也就是具體文件系統(tǒng)(例如Ext2)的掛載
  • 打開文件胜宇,我們?cè)谠L問一個(gè)文件之前首先要打開它(open)
  • 文件訪問,進(jìn)行文件的讀寫操作(read或者write)

其中第1個(gè)流程其實(shí)是建立VFS和諸如Ext4文件系統(tǒng)的關(guān)聯(lián)恢着,這樣當(dāng)用戶在后面打開某個(gè)文件的時(shí)候桐愉,VFS就知道應(yīng)該調(diào)用那個(gè)文件系統(tǒng)的函數(shù)實(shí)現(xiàn)。而第2個(gè)流程則是初始化文件系統(tǒng)必要的數(shù)據(jù)結(jié)構(gòu)和操作函數(shù)(例如read和write等)掰派,為后面的具體操作做準(zhǔn)備从诲。掛載的流程比較復(fù)雜,本文先概括的介紹一下靡羡,后續(xù)再做詳細(xì)介紹系洛。

掛載也是用戶態(tài)發(fā)起的命令,就是我們知道的mount命令略步,該命令執(zhí)行的時(shí)候需要指定文件系統(tǒng)的類型(本文假設(shè)Ext2)和文件系統(tǒng)數(shù)據(jù)的位置(也就是設(shè)備)描扯。通過這些關(guān)鍵信息,VFS就可以完成Ext2文件系統(tǒng)的初始化趟薄,并將其關(guān)聯(lián)到當(dāng)前已經(jīng)存在的文件系統(tǒng)中绽诚,也就是建立其圖2所示的文件系統(tǒng)樹。

本文不介紹代碼細(xì)節(jié)杭煎,僅僅從數(shù)據(jù)結(jié)構(gòu)方面介紹一下Linux文件系統(tǒng)掛載的具體原理恩够。如圖3是虛擬文件系統(tǒng)涉及的主要的數(shù)據(jù)結(jié)構(gòu)。在掛載的過程中羡铲,最為重要的數(shù)據(jù)結(jié)構(gòu)是vfsmount蜂桶,它代表一個(gè)掛載點(diǎn)。其次是dentry和inode也切,這兩個(gè)都是對(duì)文件的表示屎飘,且都會(huì)緩存在哈希表中以提高查找的效率妥曲。其中inode是對(duì)磁盤上文件的唯一表示,其中包含文件的元數(shù)據(jù)(管理數(shù)據(jù))和文件數(shù)據(jù)等內(nèi)容钦购,但不含文件名稱。而dentry則是為了Linux內(nèi)核中查找文件方便虛擬出來的一個(gè)數(shù)據(jù)結(jié)構(gòu)褂萧,其中包含文件名稱押桃、子目錄(如果存在的話)和關(guān)聯(lián)的inode等信息。

文件系統(tǒng)核心數(shù)據(jù)結(jié)構(gòu)

這里面dentry結(jié)構(gòu)體最為關(guān)鍵导犹,其維護(hù)了內(nèi)核中的文件目錄樹唱凯。其中里面比較重要的幾個(gè)結(jié)構(gòu)體分別是d_name、d_hash和d_subdirs谎痢。其中d_name代表一個(gè)路徑節(jié)點(diǎn)的名稱(文件夾名稱)磕昼、d_hash則用于構(gòu)建哈希表,d_subdirs則是下級(jí)目錄(或文件)的列表节猿。這樣票从,通過dentry就可以形成一個(gè)非常復(fù)雜的目錄樹。

dentry數(shù)據(jù)結(jié)構(gòu)

其中inode是文件的唯一表示滨嘱,其中除了包含元數(shù)據(jù)和數(shù)據(jù)的索引之外峰鄙,還包含關(guān)鍵操作的函數(shù)指針。比如對(duì)于文件讀寫和屬性更改等操作接口都存在該結(jié)構(gòu)體中太雨,具體如圖3所示吟榴。這里面主要涉及3個(gè)結(jié)構(gòu)體,分別是address_space囊扳、inode_operations和file_operations吩翻,其中每一個(gè)結(jié)構(gòu)體中都包含很多函數(shù)指針。

回到正題锥咸,所謂文件系統(tǒng)的掛載過程狭瞎,其實(shí)就是構(gòu)建上述幾個(gè)結(jié)構(gòu)體的過程,特別是inode結(jié)構(gòu)體的初始化她君。以Ext4為例脚作,在掛載的時(shí)候就會(huì)將其中的address_space、inode_operations和file_operations函數(shù)指針初始化為Ext4文件系統(tǒng)的函數(shù)缔刹。因此當(dāng)對(duì)文件進(jìn)行訪問的時(shí)候球涛,只要找到這個(gè)inode,就能知道是什么類型的文件系統(tǒng)校镐。

處理流程示例

我們都知道亿扁,在用戶態(tài)打開一個(gè)文件是返回的是一個(gè)文件描述符,其實(shí)也就是一個(gè)整數(shù)值鸟廓。同時(shí)从祝,訪問文件也是通過這個(gè)文件描述符進(jìn)行的襟己,如下面代碼所示的函數(shù)原型。那么操作系統(tǒng)是怎么通過這個(gè)整數(shù)值實(shí)現(xiàn)不同類型文件系統(tǒng)的訪問呢牍陌?前文我們知道不同文件系統(tǒng)的差異其實(shí)就是inode中初始化的函數(shù)指針的差異擎浴,因此問題的關(guān)鍵是這個(gè)文件描述符和inode是怎么關(guān)聯(lián)起來的。

int fd = open(const char *pathname,int flags,mode_t mode);
ssize_t read(int fd, void * buf, size_t count);

在Linux操作系統(tǒng)中毒涧,文件的打開必須要與進(jìn)程(或者線程)關(guān)聯(lián)贮预,也就是說一個(gè)打開的文件必須隸屬于某個(gè)進(jìn)程。在linux內(nèi)核當(dāng)中一個(gè)進(jìn)程通過task_struct結(jié)構(gòu)體描述契讲,而打開的文件則用file結(jié)構(gòu)體描述仿吞,打開文件的過程也就是對(duì)file結(jié)構(gòu)體的初始化的過程。在打開文件的過程中會(huì)將inode部分關(guān)鍵信息填充到file中捡偏,特別是文件操作的函數(shù)指針唤冈。在task_struct中保存著一個(gè)file類型的數(shù)組,而用戶態(tài)的文件描述符其實(shí)就是數(shù)組的下標(biāo)银伟。這樣通過文件描述符就可以很容易到找到file你虹,然后通過其中的函數(shù)指針訪問數(shù)據(jù)。

進(jìn)程與文件

例如我們以Ext2文件系統(tǒng)的寫數(shù)據(jù)為例枣申,在調(diào)用用戶態(tài)的寫數(shù)據(jù)接口的時(shí)候售葡,需要傳入文件描述符。內(nèi)核根據(jù)文件描述符找到file忠藤,然后調(diào)用函數(shù)接口(file->f_op->write)文件磁盤數(shù)據(jù)挟伙。其中file結(jié)構(gòu)體的f_op指針就是在打開文件的時(shí)候通過inode初始化的。

Ext2寫數(shù)據(jù)流程

推薦:

視頻:3個(gè)內(nèi)核的秘密模孩,讓文件系統(tǒng)在你面前“一絲不掛”

C/C++Linux服務(wù)器開發(fā)/高級(jí)架構(gòu)師 系統(tǒng)學(xué)習(xí)公開課地址

歡迎朋友們加入C/C++Linux服務(wù)器開發(fā)/高級(jí)架構(gòu)師 學(xué)習(xí)群 群內(nèi)提供免費(fèi)的C/C++Linux服務(wù)器開發(fā)/高級(jí)架構(gòu)師學(xué)習(xí)資料資料包括C/C++尖阔,Linux,golang技術(shù)榨咐,Nginx介却,ZeroMQ,MySQL块茁,Redis齿坷,fastdfs,MongoDB数焊,ZK永淌,流媒體,CDN佩耳,P2P遂蛀,K8S,Docker干厚,TCP/IP李滴,協(xié)程螃宙,DPDK,ffmpeg等)所坯!

image.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谆扎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芹助,更是在濱河造成了極大的恐慌燕酷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件周瞎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饵蒂,警方通過查閱死者的電腦和手機(jī)声诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來退盯,“玉大人彼乌,你說我怎么就攤上這事≡ㄇǎ” “怎么了慰照?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)琉朽。 經(jīng)常有香客問我毒租,道長(zhǎng),這世上最難降的妖魔是什么箱叁? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任墅垮,我火速辦了婚禮,結(jié)果婚禮上耕漱,老公的妹妹穿的比我還像新娘算色。我一直安慰自己,他們只是感情好螟够,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布灾梦。 她就那樣靜靜地躺著,像睡著了一般妓笙。 火紅的嫁衣襯著肌膚如雪若河。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天给郊,我揣著相機(jī)與錄音牡肉,去河邊找鬼。 笑死淆九,一個(gè)胖子當(dāng)著我的面吹牛统锤,可吹牛的內(nèi)容都是我干的毛俏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼饲窿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼煌寇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逾雄,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤阀溶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鸦泳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體银锻,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年做鹰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了击纬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钾麸,死狀恐怖更振,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饭尝,我是刑警寧澤肯腕,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站钥平,受9級(jí)特大地震影響实撒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帖池,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一奈惑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睡汹,春花似錦肴甸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至彤叉,卻和暖如春庶柿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秽浇。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工浮庐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柬焕。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓审残,卻偏偏與公主長(zhǎng)得像梭域,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搅轿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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