[深刻理解文件系統之四] VFS和vnode

文件系統的進化史和人類文明的進化有些相似,都是從低級、封閉乃至對抗走向高級、開放和包容。在VFS一統江湖以前,其實還有它的前身FSSFile system Switch)。當時,人們寄但願於它可以兼容各類不一樣的文件系統。FSS中重要的數據結構mount/,它和傳統indoe、文件系統類型的關係以下圖:node


 

wKioL1i1CKyxuzTcAACyqEPRLLg519.png可是FSS是短命的,被後來SVR3裏面引入的vnode快速代替。但咱們不能忘記FSS最重要的貢獻: 把不一樣的文件系統以mount的形式掛載起來。數組

SVR3最先是基於「Vnodes: An architecture for Multiple File-system  Types in Sun Unix」這篇論文,這篇論文提出了實現統一文件系統的四個要求:服務器

1.文件系統依賴層和文件系統非依賴層清晰第分開;數據結構

2.支持本地文件系統和NFS/RFS架構

3.支持NFS 服務器端ide

4.跨接口的文件系統操做應該是原子的函數

固然它的實現很複雜。其中一個主要的實現,就是從內核中去掉和具體文件系統相關的全局變量,以保證接口是可重入的。 例如,以前user結構中的u_base/u_count就須要去掉。ui

新設計的主要架構以下:
this


wKiom1i1CRbQpo0UAABov2vvipU751.png

那麼,vnode和咱們如今一般所說的vfs又有何關係呢?關聯在代碼裏又是如何實現的?這就須要瞭解vnodevfs的數據結構和各自對應的操做。spa


vnode相關的操做針對vnode,包括vop_open/vop_close/vop_rdwr/vop_ioctl/vop_select/vop_getattr/vop_setattr/vop_access


vnode數據結構的成員包括:

v_flagVROOT/VNOMAP/VNOSWAP/VNOMOUNT/VISSWAP

v_count: similar as i_count

v_shlockc: shared lock counter

v_exlockc: number of exclusive locks on the vnode

v_vfsmountedhere: points to the vfs structure of the mounted file-system

v_op: vnode operations associated with this file type

v_vfsp: points to the vfs structure for this file system

v_type: specifies the type of file that the vnode represents VREG/VDIR/VBLK/VCHR/VLINK/VFIFO/VXNAM

v_data: used to reference private data such as a copy of the on-disk inode


能夠看到,經過上面的v_vfsmountedherev_vfsp和虛擬文件系統關聯了起來。


此外,實現對不一樣文件系統的統一接口,就須要屏蔽用戶態實現io請求的差別。一種避免直接處理或引用user數據結構中的IO相關的信息的方法是把這些信息打包,這就引入了uio_iov的數據結構。 這個數據結構包含下面的成員:

uio_iov:基於user地址和字節數的iovec結構的數組指針;

uio_iovcnt: number of iovec;

uio_offset: 文件內讀和寫起始的地方

uio_segflg:代表當前請求是來自用戶態仍是內核態

uio_resid:後面未完成的IO個數


經過上面的uio數據結構,它實現了兩個主要的好處:

1. user area access was implemented so that NFS can make a call to the underlying filesystem;

2. readv()/writev() can be implemented


VFS像一個文件系統公共抽象層,或者說是父類也好。 每一個掛載的文件系統都對應一個vfs數據結構,該結構的主要成員包括vfs_ops。其中vfs_ops是每一個具體的文件系統須要實現的一組操做函數。這些操做包括:

vfs_mount()

vfs_unmount()

vfs_root():返回當前文件系統的根vnode節點,用在路徑名解析

vfs_statfs()

vfs_sync()

vfs_fid(): NFS用它來爲特殊的vnode構建一個文件句柄

vfs_vget(): NFS用它來把上面返回的文件句柄轉換成一個vnode


根據上面的數據結構和操做能夠看到:

1. vfs_ops相關的操做只是設計到文件系統層面,無論具體的vnode操做;

2. VFS主要是實現一個抽象類的功能、接口或機制,屏蔽了不一樣文件的操做上的區別,讓應用層看到全部的文件系統操做都是透明的。


討論完了vfs,再回過頭看vnode,它的主要操做以下:

vop_open():針對設備相關的文件操做,通常在vop_lookup返回vnode後調用

vop_close(): 針對設備相關的文件的操做

vop_rdwr():讀或寫文件,和具體IO相關的信息是經過uio數據結構傳遞進來的

vop_ioctl():藉助針對文件的ioctl操做,函數可以傳到設備驅動

vop_select():實現select()系統調用

vop_getattr(): stat()系統調用的實現用這個函數來填充vattr數據結構

vop_setattr():讓調用者來設置文件大小、模式、User IDgroup ID file times等屬性

vop_access():讓調用者來檢查文件讀、寫、可執行等權限

vop_lookup():根據指定目錄對應的vnode和要查找的文件/設備名, 返回指定目錄下和設備名對應的vnode

vop_create():在參數vnode指定的目錄下建立一個新文件, 文件屬性是經過參數vattr傳遞進來的。

vop_remove()刪除一個目錄entry

vop_link()

vop_rename()

vop_mkdir()

vop_rmdir()

vop_readdir()

vop_symlik()

vop_readlink()

上面都是來實現各自對應的系統調用


vop_fsync(): 把內存中任何改動的數據刷到磁盤,實現fsync()系統調用


vop_inacive():當內核中文件系統無關層沒有任何模塊再使用vnode的時候,文件系統經過這個調用來釋放這個vnode;


vop_bmap():向內核VM(Virtual memory subsystem)請求頁,以便VM可以把邏輯文件的偏移映射到物理磁盤的偏移


vop_strategy():vop_bmap()以後,VM或者buffer cache 層調用這個函數來讀取文件塊到內存中。


vop_bread():從指定的vnode對應的文件中讀取邏輯塊,而且從buffer cache中返回指向這個邏輯塊的buffer.


vop_brelse():vop_bread()調用以後,釋放buffre.


能夠看到vnode是對不一樣文件系統中各類特殊inode的統一抽象,它屏蔽底層具體文件系統的差別,向文件系統相關的系統調用層提供了統1、公共的函數接口。

相關文章
相關標籤/搜索