淺談Linux虛擬文件系統(tǒng)

1. 虛擬文件系統(tǒng)概述

1.1 VFS簡介

虛擬文件系統(tǒng)(Virtual File System,簡稱VFS)是Linux內(nèi)核的子系統(tǒng)之一,它為用戶程序提供文件和文件系統(tǒng)操作的統(tǒng)一接口,屏蔽不同文件系統(tǒng)的差異和操作細(xì)節(jié)。借助VFS可以直接使用open()、read()、write()這樣的系統(tǒng)調(diào)用操作文件,而無須考慮具體的文件系統(tǒng)和實(shí)際的存儲介質(zhì)。

舉個例子,Linux用戶程序可以通過read() 來讀取ext3、NFS、XFS等文件系統(tǒng)的文件,也可以讀取存儲在SSD、HDD等不同存儲介質(zhì)的文件,無須考慮不同文件系統(tǒng)或者不同存儲介質(zhì)的差異。

通過VFS系統(tǒng),Linux提供了通用的系統(tǒng)調(diào)用,可以跨越不同文件系統(tǒng)和介質(zhì)之間執(zhí)行,極大簡化了用戶訪問不同文件系統(tǒng)的過程。另一方面,新的文件系統(tǒng)、新類型的存儲介質(zhì),可以無須編譯的情況下,動態(tài)加載到Linux中。

"一切皆文件"是Linux的基本哲學(xué)之一,不僅是普通的文件,包括目錄、字符設(shè)備、塊設(shè)備、套接字等,都可以以文件的方式被對待。實(shí)現(xiàn)這一行為的基礎(chǔ),正是Linux的虛擬文件系統(tǒng)機(jī)制。

1.2 VFS原理

VFS之所以能夠銜接各種各樣的文件系統(tǒng),是因?yàn)樗橄罅艘粋€通用的文件系統(tǒng)模型,定義了通用文件系統(tǒng)都支持的、概念上的接口。新的文件系統(tǒng)只要支持并實(shí)現(xiàn)這些接口,并注冊到Linux內(nèi)核中,即可安裝和使用。

舉個例子,比如Linux寫一個文件:

int ret = write(fd, buf, len);

調(diào)用了write()系統(tǒng)調(diào)用,它的過程簡要如下:

  • 首先,勾起VFS通用系統(tǒng)調(diào)用sys_write()處理。
  • 接著,sys_write()根據(jù)fd找到所在的文件系統(tǒng)提供的寫操作函數(shù),比如op_write()。
  • 最后,調(diào)用op_write()實(shí)際的把數(shù)據(jù)寫入到文件中。

操作示意圖如下:

2. 虛擬文件系統(tǒng)組成部分

Linux為了實(shí)現(xiàn)這種VFS系統(tǒng),采用面向?qū)ο蟮脑O(shè)計(jì)思路,主要抽象了四種對象類型:

  • 超級塊對象:代表一個已安裝的文件系統(tǒng)。
  • 索引節(jié)點(diǎn)對象(inode):代表具體的文件。
  • 目錄項(xiàng)對象:代表一個目錄項(xiàng),是文件路徑的一個組成部分。
  • 文件對象:代表進(jìn)程打開的文件。

每個對象都包含一組操作方法,用于操作相應(yīng)的文件系統(tǒng)。

備注:Linux將目錄當(dāng)做文件對象來處理,是另一種形式的文件,它里面包含了一個或多個目錄項(xiàng)。而目錄項(xiàng)是單獨(dú)抽象的對象,主要包括文件名和索引節(jié)點(diǎn)號。因?yàn)槟夸浭强梢詫訉忧短?,以形成文件路徑,而路徑中的每一部分,其?shí)就是目錄項(xiàng)。

接下來介紹一下各個對象的作用以及相關(guān)操作。

2.1 super_block

超級塊用于存儲文件系統(tǒng)的元信息,由super_block結(jié)構(gòu)體表示,定義在<linux/fs.h>中,元信息里面包含文件系統(tǒng)的基本屬性信息,比如有:

  • 索引節(jié)點(diǎn)信息
  • 掛載的標(biāo)志
  • 操作方法 s_op
  • 安裝權(quán)限
  • 文件系統(tǒng)類型、大小、區(qū)塊數(shù)
  • 等等等等

其中操作方法 s_op 對每個文件系統(tǒng)來說,是非常重要的,它指向該超級塊的操作函數(shù)表,包含一系列操作方法的實(shí)現(xiàn),這些方法有:

  • 分配inode
  • 銷毀inode
  • 讀、寫inode
  • 文件同步
  • 等等

當(dāng)VFS需要對超級塊進(jìn)行操作時(shí),首先要在超級塊的操作方法 s_op 中,找到對應(yīng)的操作方法后再執(zhí)行。比如文件系統(tǒng)要寫自己的超級塊:

superblock->s_op->write_supper(sb);

創(chuàng)建文件系統(tǒng)時(shí),其實(shí)就是往存儲介質(zhì)的特定位置,寫入超級塊信息;而卸載文件系統(tǒng)時(shí),由VFS調(diào)用釋放超級塊。

Linux支持眾多不同的文件系統(tǒng),file_system_type結(jié)構(gòu)體用于描述每種文件系統(tǒng)的功能和行為,包括:

  • 名稱、類型等
  • 超級塊對象鏈表
    -- 等等

當(dāng)向內(nèi)核注冊新的文件系統(tǒng)時(shí),其實(shí)是將file_system_type對象實(shí)例化,然后加入到Linux的根文件系統(tǒng)的目錄樹結(jié)構(gòu)上。

2.2 inode

索引節(jié)點(diǎn)對象包含Linux內(nèi)核在操作文件、目錄時(shí),所需要的全部信息,這些信息由inode結(jié)構(gòu)體來描述,定義在<linux/fs.h>中,主要包含:

  • 超級塊相關(guān)信息
  • 目錄相關(guān)信息
  • 文件大小、訪問時(shí)間、權(quán)限相關(guān)信息
  • 引用計(jì)數(shù)
  • 等等

一個索引節(jié)點(diǎn)inode代表文件系統(tǒng)中的一個文件,只有當(dāng)文件被訪問時(shí),才在內(nèi)存中創(chuàng)建索引節(jié)點(diǎn)。與超級塊類似的是,索引節(jié)點(diǎn)對象也提供了許多操作接口,供VFS系統(tǒng)使用,這些接口包括:

  • create(): 創(chuàng)建新的索引節(jié)點(diǎn)(創(chuàng)建新的文件)
  • link(): 創(chuàng)建硬鏈接
  • symlink(): 創(chuàng)建符號鏈接。
  • mkdir(): 創(chuàng)建新的目錄。

2.3 dentry(目錄項(xiàng))

前面提到VFS把目錄當(dāng)做文件對待,比如/usr/bin/vim,usr、bin和vim都是文件,不過vim是一個普通文件,usr和bin都是目錄文件,都是由索引節(jié)點(diǎn)對象標(biāo)識。

由于VFS會經(jīng)常的執(zhí)行目錄相關(guān)的操作,比如切換到某個目錄、路徑名的查找等等,為了提高這個過程的效率,VFS引入了目錄項(xiàng)的概念。一個路徑的組成部分,不管是目錄還是普通文件,都是一個目錄項(xiàng)對象。/、usr、bin、vim都對應(yīng)一個目錄項(xiàng)對象。不過目錄項(xiàng)對象沒有對應(yīng)的磁盤數(shù)據(jù)結(jié)構(gòu),是VFS在遍歷路徑的過程中,將它們逐個解析成目錄項(xiàng)對象。

目錄項(xiàng)由dentry結(jié)構(gòu)體標(biāo)識,定義在<linux/dcache.h>中,主要包含:

  • 父目錄項(xiàng)對象地址
  • 子目錄項(xiàng)鏈表
  • 目錄關(guān)聯(lián)的索引節(jié)點(diǎn)對象
  • 目錄項(xiàng)操作指針

目錄項(xiàng)有三種狀態(tài):

  • 被使用:該目錄項(xiàng)指向一個有效的索引節(jié)點(diǎn),并有一個或多個使用者,不能被丟棄。
  • 未被使用:也對應(yīng)一個有效的索引節(jié)點(diǎn),但VFS還未使用,被保留在緩存中。如果要回收內(nèi)存的話,可以撤銷未使用的目錄項(xiàng)。
  • 負(fù)狀態(tài):沒有對應(yīng)有效的索引節(jié)點(diǎn),因?yàn)樗饕?jié)點(diǎn)被刪除了,或者路徑不正確,但是目錄項(xiàng)仍被保留了。

將整個文件系統(tǒng)的目錄結(jié)構(gòu)解析成目錄項(xiàng),是一件費(fèi)力的工作,為了節(jié)省VFS操作目錄項(xiàng)的成本,內(nèi)核會將目錄項(xiàng)緩存起來。

2.4 文件

文件對象是進(jìn)程打開的文件在內(nèi)存中的實(shí)例。Linux用戶程序可以通過open()系統(tǒng)調(diào)用來打開一個文件,通過close()系統(tǒng)調(diào)用來關(guān)閉一個文件。由于多個進(jìn)程可以同時(shí)打開和操作同一個文件,所以同一個文件,在內(nèi)存中也存在多個對應(yīng)的文件對象,但對應(yīng)的索引節(jié)點(diǎn)和目錄項(xiàng)是唯一的。

文件對象由file結(jié)構(gòu)體表示,定義在<linux/fs.h>中,主要包含:

  • 文件操作方法
  • 文件對象的引用計(jì)數(shù)
  • 文件指針的偏移
  • 打開文件時(shí)的讀寫標(biāo)識

類似于目錄項(xiàng),文件對象也沒有實(shí)際的磁盤數(shù)據(jù),只有當(dāng)進(jìn)程打開文件時(shí),才會在內(nèi)存中產(chǎn)生一個文件對象。

每個進(jìn)程都有自己打開的一組文件,由file_struct結(jié)構(gòu)體標(biāo)識,該結(jié)構(gòu)體由進(jìn)程描述符中的files字段指向。主要包括:

  • fdt
  • fd_array[NR_OPEN_DEFAULT]
  • 引用計(jì)數(shù)
    fd_array數(shù)組指針指向已打開的文件對象,如果打開的文件對象個數(shù) > NR_OPEN_DEFAULT,內(nèi)核會分配一個新數(shù)組,并將 fdt 指向該數(shù)組。

除此之外,內(nèi)核還為所有打開文件維持一張文件表,包括:

  • 文件狀態(tài)標(biāo)志
  • 文件偏移量
    關(guān)于多進(jìn)程打開同一文件以及文件共享更詳細(xì)的信息,可以閱讀《UNIX環(huán)境高級編程》第三章。

3. 總結(jié)

Linux支持了很多種類的文件系統(tǒng),包含本地文件系統(tǒng)ext3、ext4到網(wǎng)絡(luò)文件系統(tǒng)NFS、HDFS等,VFS系統(tǒng)屏蔽了不同文件系統(tǒng)的操作差異和實(shí)現(xiàn)細(xì)節(jié),提供了統(tǒng)一的實(shí)現(xiàn)框架,也提供了標(biāo)準(zhǔn)的操作接口,這大大降低了操作文件和接入新文件系統(tǒng)的難度。

原文

https://zhuanlan.zhihu.com/p/69289429

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容