inode and vnode

vivi~發表於2024-06-23

檔案系統格式

windows: FAT, NTFS;
Linux: ext, ext1/2/3/4, xfs;
網路: NFS, SMB(samba SMB/CIFS)
雲:

VFS: Linux & Mac OS 在檔案系統之上虛擬出一層檔案系統,Virtual FS;
POSIX: portable operating systerm interface of Unix.
來自使用者程序的呼叫都透過POSIX系統呼叫(open, read, write, seek)介面來和底層檔案系統(EXT, NTFS)互動;

比如同樣是create, 在windows NTFS檔案系統中用createprocess, 在UNIX中用fork, 那麼虛擬層VFS中實現POSIX介面來統一它們的結構,方便和user space互動。

Vnode 是 virtual inode。
每個開啟的檔案或目錄都有一個關聯的vnode。是記憶體抽象的。
Vnode 包含有關檔案的一些資料,但僅包含在檔案生命週期內不會更改的屬性
它抽象了 inode 的大部分內容(inode 可以是其資料欄位之一),但也捕獲了對檔案、鎖等的操作。
這使得它能夠支援非基於 inode 的檔案系統,特別是網路檔案系統。

對於 vfs 型別,其虛擬函式表 struct vfsops,包含了一系列的函式指標,用來執行諸如 mount、unmount、sync 和 vget 等操作。
對於 vnode 型別也是類似的,其虛擬函式表 struct vnodeops,包含 open、rdwr 和 close 等函式,還有create、unlink 和 rename 等函式。一些函式是針對特定的檔案型別的,比如 readlink、mkdir、readdir 和 rmdir。
vnode 例項用來進行跟蹤開啟的檔案。它包含 struct *vnodeops 指標

inode 和 vnode的理解

inode 指的是檔案的後設資料,是檔案系統層面的結構,在資料塊中的物理位置,存在於具體的檔案系統中,只對具體的檔案系統有意義:

NTFS, FAT, ext3, xfs, NFS, SMBAFS
inode 本身不儲存檔名

vnode 是 unit-like作業系統中的抽象層,為不同檔案系統提供統一的介面。

用於代表所有檔案系統的檔案或目錄,包含指向具體檔案系統操作的指標。
可以統一的處理各種檔案系統。

每個開啟的檔案或目錄都有一個關聯的vnode。是記憶體抽象的。
Vnode 包含有關檔案的一些資料,但僅包含在檔案生命週期內不會更改的屬性

vnode 本身不儲存檔名

inode 是檔案系統級別的,vnode是作業系統級別的,為所有檔案系統提供一個統一的介面
vnode只在檔案開啟時候才會存在,它呼叫inode的資訊,但是windows怎麼做呢?

inode

是unix中檔案的後設資料,包含:
軟、硬連結;
owner, group;
ACLs;
資料塊指標;

ls -le 中的資料幾乎都是從inode來的

vnode

表示檔案的抽象介面,指向檔案?
當應用程式請求開啟檔案, 核心查詢如果快取中沒有的話,就會建立一個vnode。
然後開始填充vnode,檢視請求的檔案路徑位於哪個檔案系統上,如果在linux上,就用linux的
檔案系統驅動來填充? 怎麼理解這裡的檔案系統驅動?
如果位於NTFS,就用ntfs的驅動。。

當應用程式要讀檔案時候,使用vnode的資訊,函式指標,進行操作。

擴充套件

inode 指向資料塊的指標

硬連結兩個檔名,指向同一份檔案data;
多個檔名 指向同一個檔案data;

軟連線可以跨檔案系統,類似於 Windows 的快捷方式;

用 ln filename hardfilename, 建立一個硬連結;
用ls -li 檢視原始檔和硬連結都有相同的inode,指向同一個物理資料塊;
修改hardfilename內容,檢視原始檔,內容顯示的也是修改後的;

https://www.jianshu.com/p/dde6a01c4094

ln -s 建立一個軟連線,發現它指向的inode與原始檔不同, 軟連線的inode中指向的資料塊中存放的是原始檔的路徑;

刪除原始檔之後,讀取硬連結,發現內容還在,因為硬連結的inode 依然指向那個data block,data block並未被釋放掉;
而軟連線找不到內容,因為軟連線指向的絕對路徑原始檔被刪了;

再擴充套件 檔案描述符

https://www.cnblogs.com/jiangzhaowei/p/4154834.html
當程序開啟一個檔案時,核心就會建立一個新的file物件;
file物件中描述了檔案的開啟模式,讀寫位置等重要資訊;
file物件不是專屬於某個程序的,不同程序的檔案描述符表中的指標可以指向相同的file物件,從而共享這個開啟的檔案;
file物件有引用計數,記錄了引用這個物件的檔案描述符個數,只有當引用計數為0時,核心才銷燬file物件,
因此某個程序關閉檔案,不影響與之共享同一個file物件的程序.

dentry物件代表一個獨立的檔案路徑,如果一個檔案路徑被開啟多次,那麼會建立多個file物件,但它們都指向同一個dentry物件。
dentry物件中又包含一個指向inode物件的指標。inode物件代表一個獨立檔案。因為存在硬連結與符號連結,因此不同的dentry物件可以指向相同的inode物件.
inode 物件包含了最終對檔案進行操作所需的所有資訊,如檔案系統型別、檔案的操作方法、檔案的許可權、訪問日期等。

來到vnode的擴充套件部分

https://juicefs.com/zh-cn/blog/engineering/how-support-multiple-file-systems

對於 vfs 型別,其虛擬函式表 struct vfsops,包含了一系列的函式指標,用來執行諸如 mount、unmount、sync 和 vget 等操作。
對於 vnode 型別也是類似的,其虛擬函式表 struct vnodeops,包含 open、rdwr 和 close 等函式,還有create、unlink 和 rename 等函式。一些函式是針對特定的檔案型別的,比如 readlink、mkdir、readdir 和 rmdir。
vnode 例項用來進行跟蹤開啟的檔案。它包含 struct *vnodeops 指標

我們可以在此處找到檔案物件,struct file 的例項。在檔案的所有其他內容中,最值得注意的是一個欄位 loff_t f_pos,它表示檔案當前位置距離檔案起始位置的偏移量(以位元組為單位)。

檔案的類是透過一個虛擬函式表來定義。我們可以找到一個指標 struct file_operations *f_op 。
它展示了檔案可以執行的所有操作,其中最常見的是開啟(open)、關閉(close)、定位(lseek)、讀取(read)和寫入(write)。
https://wushifublog.com/2020/05/22/深入理解Linux核心——VFS/

擴充套件: poxis中的檔案鎖

POSIX 標準是要求透過 fcntl() 系統呼叫實現一個檔案鎖的機制,這樣就能避免競爭關係。
這個檔案鎖可以對整個檔案或者檔案中的某個區域(小到一個位元組)進行鎖定,由於可以鎖檔案的部分內容,所以一個程序可以同時獲取同一個檔案的多個鎖。

在 Linux 中可以透過 fcntl() & flock() 系統呼叫對檔案進行上鎖。通常在類 unix 系統中,flock() 系統呼叫會無視 MS_MANDLOCK 的掛載標誌,只產生勸告鎖。

Linux 對於勸告鎖和強制鎖都有實現。一個程序獲取勸告鎖的方式有2種:

透過 flock() 系統呼叫,這個鎖只能對整個檔案上鎖
透過 fcntl() 系統呼叫,可以檔案的特定部分進行上鎖

相關文章