天天看點

[深入了解檔案系統之四] VFS和vnode

檔案系統的進化史和人類文明的進化有些類似,都是從低級、封閉乃至對抗走向進階、開放和包容。在VFS一統江湖之前,其實還有它的前身FSS(File system Switch)。當時,人們寄希望于它能夠相容各種不同的檔案系統。FSS中重要的資料結構mount/,它和傳統indoe、檔案系統類型的關系如下圖:

SVR3最早是基于“Vnodes: An architecture for Multiple File-system  Types in Sun Unix”這篇論文,這篇論文提出了實作統一檔案系統的四個要求:

1.檔案系統依賴層和檔案系統非依賴層清晰第分開;

2.支援本地檔案系統和NFS/RFS

3.支援NFS 伺服器端

4.跨接口的檔案系統操作應該是原子的

當然它的實作很複雜。其中一個主要的實作,就是從核心中去掉和具體檔案系統相關的全局變量,以保證接口是可重入的。 例如,之前user結構中的u_base/u_count就需要去掉。

新設計的主要架構如下:

<a href="https://s2.51cto.com/wyfs02/M00/8E/14/wKiom1i1CRbQpo0UAABov2vvipU751.png" target="_blank"></a>

那麼,vnode和我們現在通常所說的vfs又有何關系呢?關聯在代碼裡又是如何實作的?這就需要了解vnode和vfs的資料結構和各自對應的操作。

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

vnode資料結構的成員包括:

v_flag: VROOT/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_vfsmountedhere和v_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 ID、group 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的統一抽象,它屏蔽底層具體檔案系統的差異,向檔案系統相關的系統調用層提供了統一、公共的函數接口。

本文轉自存儲之廚51CTO部落格,原文連結:http://blog.51cto.com/xiamachao/1901980 ,如需轉載請自行聯系原作者

繼續閱讀