国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

解鎖Linux內核黑科技:VFS虛擬文件系統詳解

系統 Linux
在 Linux 系統中,“一切皆文件” 的理念深入人心,而 VFS 正是這一理念的重要體現。它將不同類型的文件系統,如基于磁盤的文件系統(如ext4、XFS 等)、網絡文件系統(如 NFS、CIFS 等)、虛擬文件系統(如 /proc、/sys 等),都統一抽象成可以通過文件操作接口(如open、close、read、write 等)訪問的對象 。

在Linux內核的廣袤世界里,隱藏著許多精妙的設計,其中虛擬文件系統(VFS)堪稱一顆璀璨的明珠。你是否好奇,為何在 Linux 系統中,無論是常見的本地磁盤文件系統,還是復雜的網絡文件系統,我們都能用統一的方式去操作文件和目錄?又是什么神奇的機制,讓 Linux 能輕松支持種類繁多的文件系統,從古老的 ext2 到如今的 ext4,從分布式的 Ceph 到網絡共享的 NFS?

答案就在 VFS 之中。它就像一個強大的幕后協調者,在用戶與各種千差萬別的文件系統之間,搭建起一座溝通的橋梁,讓一切變得簡單而有序。今天,就讓我們一同揭開 VFS 的神秘面紗,深入探索其內部的運作機制,領略 Linux 內核設計的智慧魅力 。

一、VFS是什么?

在日常生活中,我們可能會遇到這樣的情況:家里有不同的房間,每個房間都有對應的鑰匙。如果沒有統一的鑰匙管理系統,我們每次找鑰匙就會很麻煩,可能要在一堆鑰匙中翻找半天。但如果有一個類似于 “萬能鑰匙接口” 的東西,它可以適配各種鎖芯,只要把不同的鑰匙適配到這個接口上,我們就能用一種統一的方式去開鎖,這會大大提高我們的效率。

在 Linux 內核的世界里,VFS(Virtual File System)就扮演著這樣一個 “萬能鑰匙接口” 的角色 。VFS 是 Linux 內核中一個非常關鍵的抽象層,它的核心使命是為所有類型的文件系統提供一個統一的訪問接口。簡單來說,無論底層是 ext4、XFS 這樣常見的本地磁盤文件系統,還是像 NFS(Network File System)這樣的網絡文件系統,又或是像 procfs、sysfs 這類特殊用途的文件系統,VFS 都能讓它們在 Linux 系統中和諧共處,并為用戶和應用程序提供一致的操作方式。

VFS 就像是一個智能的翻譯官,它把用戶和應用程序發出的各種文件操作請求,比如打開文件、讀取文件、寫入文件等,準確無誤地翻譯成底層不同文件系統能夠理解的指令。同時,它又把底層文件系統返回的結果,以統一的格式呈現給用戶和應用程序。這樣一來,用戶和應用程序就完全不用關心底層文件系統的具體實現細節,只需要和 VFS 進行交互就可以了,極大地簡化了文件操作的復雜性。

另外簡單提一下兩個數據結構:

  • 每種注冊到內核的文件系統類型以struct file_system_type結構表示,每種文件系統類型中都有一個鏈表,指向所有屬于該類型的文件系統的超級塊。
  • 當一個文件系統掛載到內核文件系統的目錄樹上,會生成一個掛載點,用來管理所掛載的文件系統的信息。該掛載點用一個struct vfsmount結構表示。

1.1文件系統象層

能夠使用通用接口對所有類型的文件系統進行操作,是因為內核在它的底層文件系統接口上建立了一個抽象層。 VFS抽象層之所以能夠銜接各種各樣的文件系統,是因為它定義了所有文件系統都支持的、基本的、概念上的接口和數據結構。

1.2Unix文件系統

Unix使用四種和文件系統相關的傳統抽象概念:文件、目錄項、索引節點和安裝節點 。 linux系統中所有都看作是文件,文件通過目錄組織起來。在Unix系統當中,目錄屬于普通文件,它列出包含在其中的所有文件。 Unix系統當中將文件的相關信息和文件本身這兩個概念加以區分,例如訪問控制權限等。

文件的相關信息,有時也被稱為文件的元數據,被存儲在單獨的數據結構當中,該結構被稱之為索引節點(inode)。 對于其他的一些文件系統,比如FAT NTFS,他們沒有索引節點的概念,但是如果需要在Unix系統中工作的話,還是需要進行封裝,封裝成適合Unix系統的格式。

二、VFS的關鍵特性

2.1統一接口

VFS 提供的統一接口,就像是一個標準化的工具盒,里面裝著各種標準工具,無論面對什么樣的文件系統 “工作”,都能使用這些標準工具來完成 。在 Linux 系統中,常見的文件系統操作,如創建文件、讀取文件、寫入文件、刪除文件、打開文件、關閉文件、重命名文件、獲取文件屬性等,VFS 都為它們提供了統一的系統調用接口。例如,當我們使用open函數來打開一個文件時,無論這個文件是存儲在本地的 ext4 文件系統上,還是位于遠程的 NFS 文件系統中,我們調用open函數的方式和參數都是一樣的。

同樣,read函數用于讀取文件內容,write函數用于寫入文件內容,close函數用于關閉文件,這些函數的使用方式不會因為底層文件系統的不同而改變。對于應用程序開發者來說,他們只需要熟悉這些統一的接口,就可以輕松地編寫與文件系統交互的代碼,而無需花費大量時間去了解不同文件系統的復雜細節。

2.2多文件系統支持

Linux 系統的一大優勢就是能夠同時掛載多種不同類型的文件系統,這都得益于 VFS 強大的多文件系統支持能力。在一臺 Linux 服務器上,我們可能會同時掛載 ext4 文件系統用于存儲系統文件和用戶數據,掛載 NFS 文件系統用于訪問遠程網絡存儲設備上的文件,掛載 procfs 文件系統用于獲取系統進程信息,掛載 sysfs 文件系統用于訪問內核對象和設備信息等。

VFS 就像是一個高效的交通樞紐管理員,負責協調管理這些不同文件系統的工作 。當用戶發起一個文件操作請求時,VFS 會根據文件的路徑信息,準確地判斷出該請求應該由哪個文件系統來處理,然后將請求轉發給相應的文件系統驅動程序。例如,當用戶訪問/home/user/data.txt這個文件時,VFS 會根據/home所在的文件系統信息,確定該文件位于 ext4 文件系統上,然后調用 ext4 文件系統的驅動程序來完成文件的訪問操作;如果用戶訪問/mnt/nfs_share/file.txt,VFS 則會判斷出這是一個 NFS 文件系統上的文件,進而將請求轉發給 NFS 文件系統驅動程序。這種多文件系統支持的特性,使得 Linux 系統能夠適應各種復雜的應用場景,滿足不同用戶的多樣化需求。

2.3抽象對象模型

VFS 通過一套抽象對象模型來管理文件系統,這套模型主要包括超級塊(superblock)、索引節點(inode)、目錄項(dentry)和文件對象(file),它們相互協作,構成了 VFS 管理文件系統的堅實基礎。

(1)超級塊對象super block

超級塊就像是文件系統的 “總管家”,它存儲了整個文件系統的關鍵控制信息 。每個文件系統都有一個對應的超級塊,其中包含了文件系統的類型、塊大小、inode 表信息、空閑塊列表、文件系統的狀態等重要內容。超級塊在文件系統掛載時被讀取到內存中,并且在文件系統的整個生命周期內都發揮著重要作用。它為文件系統的管理和操作提供了全局的視角,比如通過超級塊可以快速了解文件系統的基本屬性,以及獲取文件系統中其他重要數據結構的位置信息。

struct super_block {
/* 全局鏈表元素 */
struct list_head s_list;
/* 底層文件系統所在的設備 */
dev_t s_dev;
/* 文件系統中每一塊的長度 */
unsigned long s_blocksize;
/* 文件系統中每一塊的長度(以2為底的對數) */
unsigned char s_blocksize_bits;
/* 是否需要向磁盤回寫 */
unsigned char s_dirt;
unsigned long long s_maxbytes; /* Max file size */
/* 文件系統類型 */
struct file_system_type *s_type;
/* 超級塊操作方法 */
const struct super_operations *s_op;
struct dquot_operations *dq_op;
struct quotactl_ops *s_qcop;
const struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
/* 全局根目錄的dentry */
struct dentry *s_root;
struct rw_semaphore s_umount;
struct mutex s_lock;
int s_count;
int s_need_sync;
atomic_t s_active;
#ifdef CONFIG_SECURITY
void *s_security;
#endif
struct xattr_handler **s_xattr;
/* 超級塊管理的所有inode的鏈表 */
struct list_head s_inodes; /* all inodes */
/* 臟的inode的鏈表 */
struct list_head s_dirty; /* dirty inodes */
struct list_head s_io; /* parked for writeback */
struct list_head s_more_io; /* parked for more writeback */
struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */
/* file結構的鏈表,該超級塊上所有打開的文件 */
struct list_head s_files;
/* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
/* 不再使用的dentry的LRU鏈表 */
struct list_head s_dentry_lru; /* unused dentry lru */
int s_nr_dentry_unused; /* # of dentry on lru */struct block_device *s_bdev;
struct mtd_info *s_mtd;
/* 相同文件系統類型的超級塊鏈表的節點 */
struct list_head s_instances;
struct quota_info s_dquot; /* Diskquota specific options */int s_frozen;
wait_queue_head_t s_wait_unfrozen;char s_id[32]; /* Informational name */void *s_fs_info; /* Filesystem private info */
fmode_t s_mode;/*
* The next field is for VFS *only*. No filesystems have any business
* even looking at it. You had been warned.
*/
struct mutex s_vfs_rename_mutex; /* Kludge *//* Granularity of c/m/atime in ns.
Cannot be worse than a second */
u32 s_time_gran;/*
* Filesystem subtype. If non-empty the filesystem type field
* in /proc/mounts will be "type.subtype"
*/
char *s_subtype;/*
* Saved mount options for lazy filesystems using
* generic_show_options()
*/
char *s_options;
};

s_list:是一個list_head結構體對象。list_head結構體如下定義。內核中使用一個雙向環形鏈表將所有超級塊連起來管理,即每個超級塊的s_list屬性都包含了指向內核鏈表中前一個元素和后一個元素的指針。全局變量super_blocks用于指向鏈表中第一個元素。Linux內核經常用該對象間接定義雙向循環鏈表來管理數據。

struct{
 
    list_head *prev;
 
    list_head *next;
 
}
  • s_blocksize:文件系統中數據塊大小,單位是字
  • s_dirt:臟位,在具體的硬件設備中有關于其文件系統的數據,將設備掛載以后,會用其關于文件系統的數據來初始化內存中的super_block結構體對象。而VFS是允許對超級塊對象進行修改的,修改后的數據最終是要寫回磁盤對應區域的。s_dirt用于判斷超級塊對象中數據是否臟了即被修改過了,即與磁盤上的超級塊區域是否一致。
  • s_dirty:臟inode的雙向循環鏈表,用于同步內存數據和底層存儲介質。當我們在用戶去用open打開一個文件,內存中會創建dentry和inode,當我們用write往文件中寫入數據,則該inode臟了,將其加入到s_dirty鏈表
  • s_files:該超級塊表是的文件系統中所有被打開的文件。
  • s_type:是指向file_system_type類型的指針,file_system_type結構體用于保存具體的文件系統的信息。
  • s_op:super_operations結構體類型的指針,因為一個超級塊對應一種文件系統,而每種文件系統的操作函數可能是不同的。super_operations結構體由一些函數指針組成,這些函數指針用特定文件系統的超級塊區域操作函數來初始化。比如里邊會有函數實現獲取和返回底層文件系統inode的方法。
  • s_inodes:是一個list_head結構體對象,指向超級塊對應文件系統中的所有inode索引節點的鏈表。

(2)索引節點對象inode

索引節點則是文件或目錄的 “信息卡片”,每個文件或目錄在文件系統中都對應一個唯一的 inode 。inode 中存儲了文件的元數據,如文件的大小、權限、所有者、創建時間、修改時間、訪問時間、文件數據塊的位置信息等。inode 不包含文件的名字,文件名是通過目錄項來管理的。當我們對文件進行操作時,VFS 首先會通過文件名找到對應的 inode,然后根據 inode 中的信息來執行具體的操作,比如讀取文件數據時,就需要根據 inode 中記錄的數據塊位置信息,從磁盤上讀取相應的數據塊。

struct inode {
/* 全局的散列表 */
struct hlist_node i_hash;
/* 根據inode的狀態可能處理不同的鏈表中(inode_unused/inode_in_use/super_block->dirty) */
struct list_head i_list;
/* super_block->s_inodes鏈表的節點 */
struct list_head i_sb_list;
/* inode對應的dentry鏈表,可能多個dentry指向同一個文件 */
struct list_head i_dentry;
/* inode編號 */
unsigned long i_ino;
/* 訪問該inode的進程數目 */
atomic_t i_count;
/* inode的硬鏈接數 */
unsigned int i_nlink;
uid_t i_uid;
gid_t i_gid;
/* inode表示設備文件時的設備號 */
dev_t i_rdev;
u64 i_version;
/* 文件的大小,以字節為單位 */
loff_t i_size;
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
/* 最后訪問時間 */
struct timespec i_atime;
/* 最后修改inode數據的時間 */
struct timespec i_mtime;
/* 最后修改inode自身的時間 */
struct timespec i_ctime;
/* 以block為單位的inode的大小 */
blkcnt_t i_blocks;
unsigned int i_blkbits;
unsigned short i_bytes;
/* 文件屬性,低12位為文件訪問權限,同chmod參數含義,其余位為文件類型,如普通文件、目錄、socket、設備文件等 */
umode_t i_mode;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
/* inode操作 */
const struct inode_operations *i_op;
/* file操作 */
const struct file_operations *i_fop;
/* inode所屬的super_block */
struct super_block *i_sb;
struct file_lock *i_flock;
/* inode的地址空間映射 */
struct address_space *i_mapping;
struct address_space i_data;
#ifdef CONFIG_QUOTA
struct dquot *i_dquot[MAXQUOTAS];
#endif
struct list_head i_devices; /* 若為設備文件的inode,則為設備的打開文件列表節點 */
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; /* 若為塊設備的inode,則指向該設備實例 */
struct cdev *i_cdev; /* 若為字符設備的inode,則指向該設備實例 */
};__u32 i_generation;#ifdef CONFIG_FSNOTIFY
__u32 i_fsnotify_mask; /* all events this inode cares about */
struct hlist_head i_fsnotify_mark_entries; /* fsnotify mark entries */
#endif#ifdef CONFIG_INOTIFY
struct list_head inotify_watches; /* watches on this inode */
struct mutex inotify_mutex; /* protects the watches list */
#endifunsigned long i_state;
unsigned long dirtied_when; /* jiffies of first dirtying */unsigned int i_flags; /* 文件打開標記,如noatime */atomic_t i_writecount;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
#ifdef CONFIG_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
void *i_private; /* fs or device private pointer */
};

以下是通用的inode對象結構體定義:

  • i_no:便是inode的唯一性編號
  • i_count:訪問該inode結構體對象的進程數
  • i_nlink:硬鏈接計數,等于0時將文件從磁盤移除。
  • i_hash:指向哈希鏈表指針,用于查詢,已經inode號碼和對應超級塊的時候,通過哈希表來快速查詢地址。具體看下邊管理inode節點。也是list_head類型對象,這種對象就對應了一個雙向循環鏈表。
  • i_dentry:指向目錄項鏈表指針,因為一個inode可以對象多個dentry,因此用一個鏈表將于本inode關聯的目錄項都連在一起。
  • i_op:索引節點操作函數指針,指向了inode_operation結構體,提供與inode相關的操作
  • i_fop:指向file_operations結構提供文件操作,在file結構體中也有指向file_operations結構的指針。
  • i_sb:inode所屬文件系統的超級塊指針

管理inode節點的四個鏈表(前兩個是全局鏈表,第三個在超級塊中):

  • inode_unused:目前未被使用的inode節點鏈表,即尚在內存中沒有銷毀,但是沒有進程使用,i_count為0。
  • inode_in_use:當前正在使用的inode鏈表,i_count > 0且 i_nlink > 0
  • super_block中的s_dirty:將所有修改過的inode鏈接起來
  • inode_hashtable:為了加快查找效率,將正在使用的和臟的inode放入一個哈希表中,但是不同的inode的哈希值可能相等,hash值相等的inode哦那個過i_hash成員連接。

注意是所有位于內存中的inode會存放在一個名為inode_hashtable的全局哈希表中,如果inode還在磁盤,沒有緩存到內存,則不會加入全局哈希表。inode_hashtable加快了對索引節點對象的搜索,但前提是要知道inode號碼和對應的超級塊對象。在inode_hashtable哈希表中的元素是鏈表,是通過inode對象中的i_hash成員鏈接起來的雙向循環鏈表,在這個子鏈表中對應的inode的哈希值是相等的。即inode_hashtable本質是一個數據和鏈表的結合體。

(3)目錄項對象

目錄項是文件系統層次結構的 “導航員”,它用于表示文件系統中的目錄和文件,是連接文件名和inode的橋梁 。在文件系統的路徑中,每一部分都對應一個目錄項,例如/home/user/data.txt這個路徑中,/、home、user和data.txt分別是一個目錄項。目錄項中包含了文件名、指向inode 的指針以及一些其他的元數據。通過目錄項,VFS 可以快速地從文件系統的根目錄開始,沿著目錄層次結構找到目標文件或目錄的 inode,從而實現對文件的訪問。同時,目錄項還會被緩存起來,形成目錄項高速緩存(dentry cache),這樣在下次訪問相同的文件或目錄時,可以大大提高查找速度。

struct dentry {
atomic_t d_count;
unsigned int d_flags; /* protected by d_lock */
spinlock_t d_lock; /* per dentry lock */
/* 該dentry是否是一個裝載點 */
int d_mounted;
/* 文件所屬的inode */
struct inode *d_inode;
/*
* The next three fields are touched by __d_lookup. Place them here so they all fit in a cache line.
*/
/* 全局的dentry散列表 */
struct hlist_node d_hash; /* lookup hash list */
/* 父目錄的dentry */
struct dentry *d_parent; /* parent directory */
/* 文件的名稱,例如對/tmp/a.sh,文件名即為a.sh */
struct qstr d_name;
/* 臟的dentry鏈表的節點 */
struct list_head d_lru; /* LRU list */
/*
* d_child and d_rcu can share memory
*/
union {
struct list_head d_child; /* child of parent list */
struct rcu_head d_rcu;
} d_u;
/* 該dentry子目錄中的dentry的節點鏈表 */
struct list_head d_subdirs; /* our children */
/* 硬鏈接使用幾個不同名稱表示同一個文件時,用于連接各個dentry */
struct list_head d_alias; /* inode alias list */
unsigned long d_time; /* used by d_revalidate */
const struct dentry_operations *d_op;
/* 所屬的super_block */
struct super_block *d_sb; /* The root of the dentry tree */
void *d_fsdata; /* fs-specific data */
/* 如果文件名由少量字符組成,在保存在這里,加速訪問 */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
  • d_count:目錄項對象引用計數器
  • d_name:文件名
  • d_inode:inode節點的指針,便于快速找到對應的索引節點
  • d_sb:指向對應超級塊的指針
  • d_op:指向dentry對應的操作函數集
  • d_subdirs & d_child:某目錄的d_subdirs與該目錄下所有文件的d_child成員一起形成一個雙向循環鏈表,將該目錄下的所有文件連接在一起,目的是保留文件的目錄結構,即一個d_subdirs和多個d_child一起形成鏈表,d_subdirs對應文件在d_child對應文件的上一層目錄。具體可見下圖。
  • d_parent:指向父目錄的dentry對象。

通過d_subdirs和d_child把同一目錄下的文件都連接了起來形成鏈表,然后通過d_parent成員可以確定該鏈表對應的文件所在的目錄,這三個成員一起就能完全保留文件之間的目錄層次關系。比如當移動文件的時候,只需要將dentry對象從舊得父dentry鏈表(d_subdirs)上脫離,鏈接到新的父dentry的d_subdirs鏈表上,并將d_parent成員指向新的父dentry即可??梢钥吹揭苿游募]有移動底層文件,甚至沒有改變inode,只是改變了緩存中的dentry(最終改變目錄文件),因此在同一個文件系統中移動文件會很快,但是跨文件系統就會改變inode和底層數據區了,因此速度很慢。

(4)文件對象

文件對象是表示打開文件的 “活動記錄”,當一個文件被打開時,VFS 會創建一個對應的文件對象 。文件對象中包含了指向 inode 的指針、當前文件的讀寫位置、文件操作的狀態標志以及指向文件操作函數集的指針等信息。文件對象主要用于在文件打開期間,記錄和管理文件的操作狀態,例如當我們對一個打開的文件進行讀寫操作時,文件對象會記錄當前的讀寫位置,以便下次繼續進行讀寫操作。文件對象還提供了對文件進行各種操作的接口,這些接口最終會調用 inode 中定義的文件操作函數集來完成實際的文件操作。

<pre style="overflow-wrap: break-word; margin: 0px; padding: 0px; white-space: normal; background: rgb(84, 82, 82); color: rgb(238, 238, 238); font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">struct file { union { struct list_head fu_list; //文件對象鏈表指針linux/include/linux/list.h struct rcu_head fu_rcuhead; //RCU(Read-Copy Update)是Linux 2.6內核中新的鎖機制 } f_u; struct path f_path; //包含dentry和mnt兩個成員,用于確定文件路徑 #define f_dentry f_path.dentry //f_path的成員之一,當前文件的dentry結構 #define f_vfsmnt f_path.mnt //表示當前文件所在文件系統的掛載根目錄 const struct file_operations *f_op; //與該文件相關聯的操作函數 atomic_t f_count; //文件的引用計數(有多少進程打開該文件) unsigned int f_flags; //對應于open時指定的flag mode_t f_mode; //讀寫模式:open的mod_t mode參數 off_t f_pos; //該文件在當前進程中的文件偏移量 struct fown_struct f_owner; //該結構的作用是通過信號進行I/O時間通知的數據。 unsigned int f_uid, f_gid; //文件所有者id,所有者組id struct file_ra_state f_ra; //在linux/include/linux/fs.h中定義,文件預讀相關 unsigned long f_version; //記錄文件的版本號,每次使用后都自動遞增。 #ifdef CONFIG_SECURITY void *f_security; //用來描述安全措施或者是記錄與安全有關的信息。 #endif /* needed for tty driver, and maybe others */ void *private_data; //可以用字段指向已分配的數據 #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; 文件的事件輪詢等待者鏈表的頭, spinlock_t f_ep_lock; f_ep_lock是保護f_ep_links鏈表的自旋鎖。 #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; 文件地址空間的指針 };</pre>
 
<pre style="overflow-wrap: break-word; margin: 0px; padding: 0px; white-space: normal; background: rgb(84, 82, 82); color: rgb(238, 238, 238); font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">struct files_struct { atomic_t count; /* 共享該表的進程數 */ rwlock_t file_lock; /* 保護該結構體的鎖*/ int max_fds; /*當前文件對象的最大數*/ int max_fdset; /*當前文件描述符的最大數*/ int next_fd; /*已分配的文件描述符加1*/ struct file ** fd; /* 指向文件對象指針數組的指針 */ fd_set *close_on_exec; /*指向執行exec()時需要關閉的文件描述符*/ fd_set *open_fds; /*指向打開文件描述符的指針*/ fd_set close_on_exec_init; /* 執行exec()時關閉的初始文件*/ fd_set open_fds_init; /*文件描述符的初值集合*/ struct file * fd_array[32]; /* 文件對象指針的初始化數組*/ };</pre>

三、VFS的工作原理

VFS 之所以能夠銜接各種各樣的文件系統,是因為它抽象了一個通用的文件系統模型,定義了通用文件系統都支持的、概念上的接口。新的文件系統只要支持并實現這些接口,并注冊到 Linux 內核中,即可安裝和使用。

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

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

調用了write()系統調用,它的過程簡要如下:

  • 首先,勾起 VFS 通用系統調用sys_write()處理。
  • 接著,sys_write()根據fd找到所在的文件系統提供的寫操作函數,比如op_write()。
  • 最后,調用op_write(

圖片圖片

3.1文件操作流程示例

為了更深入地理解 VFS 的工作原理,我們以打開文件這一常見操作為例,詳細剖析其背后的具體流程。當我們在應用程序中調用open函數打開一個文件時,看似簡單的一個操作,實際上在 Linux 內核中涉及到多個步驟和 VFS 關鍵數據結構的協同工作 。

應用程序發起調用:應用程序中執行open函數,例如int fd = open("/home/user/data.txt", O_RDONLY);,這里傳遞了文件的路徑/home/user/data.txt以及打開模式O_RDONLY(表示只讀打開)。此時,應用程序通過系統調用接口陷入內核態,將控制權交給內核中的 VFS 模塊來處理這個請求。

路徑解析與目錄項查找:VFS 首先會對傳入的文件路徑進行解析。它從根目錄/開始,逐步解析路徑中的每一個部分。在這個過程中,VFS 會利用目錄項高速緩存(dentry cache)來加速查找過程。目錄項高速緩存中存儲了最近訪問過的目錄項信息,當 VFS 解析路徑時,會首先在緩存中查找對應的目錄項。

如果在緩存中找到,就可以直接獲取該目錄項的相關信息,避免了對磁盤的直接訪問,大大提高了查找效率;如果緩存中沒有命中,VFS 就需要從磁盤上讀取目錄項信息,并將其添加到緩存中,以便下次訪問時能夠快速命中 。對于/home/user/data.txt這個路徑,VFS 會依次查找根目錄/的目錄項、home目錄的目錄項、user目錄的目錄項,最后找到data.txt文件的目錄項。每個目錄項都包含了文件名以及指向對應索引節點(inode)的指針。

索引節點獲取與文件對象創建:通過找到的文件目錄項,VFS 可以獲取到對應的索引節點。索引節點中存儲了文件的元數據,如文件的大小、權限、所有者、創建時間、修改時間、數據塊位置信息等。如果索引節點不在內存中,VFS 會從磁盤上讀取該索引節點并將其加載到內存中 。接下來,VFS 會為打開的文件創建一個文件對象。

文件對象中包含了指向索引節點的指針、當前文件的讀寫位置、文件操作的狀態標志以及指向文件操作函數集的指針等信息。文件對象的創建標志著文件已經被成功打開,應用程序可以通過返回的文件描述符(在上述例子中,fd就是返回的文件描述符)來對文件進行后續的操作,如讀取文件內容、寫入文件內容等 。

3.2與底層文件系統的交互

VFS 作為一個抽象層,與底層各種具體的文件系統之間有著緊密的交互關系。當 VFS 接收到應用程序的文件操作請求后,它需要根據文件路徑確定對應的底層文件系統,并將操作請求傳遞給底層文件系統的具體實現 。

確定底層文件系統:VFS 在掛載文件系統時,會為每個掛載的文件系統創建一個對應的超級塊(superblock),超級塊中包含了文件系統的類型、掛載點等重要信息。當 VFS 接收到文件操作請求時,它會根據文件路徑中的掛載點信息,找到對應的超級塊,從而確定該文件屬于哪個底層文件系統 。例如,對于/home/user/data.txt這個文件路徑,如果/home掛載的是 ext4 文件系統,VFS 就會根據/home對應的超級塊信息,確定該文件由 ext4 文件系統來處理。

操作請求傳遞:一旦確定了底層文件系統,VFS 就會將文件操作請求傳遞給該文件系統的具體實現。每個文件系統都實現了一組與文件操作相關的函數,這些函數被封裝在一個函數指針表中,稱為文件操作函數集(file_operations) 。例如,對于打開文件操作,ext4 文件系統會實現自己的open函數,VFS 會調用 ext4 文件系統的open函數來完成實際的文件打開操作。在傳遞操作請求時,VFS 會將文件對象、索引節點以及其他相關參數傳遞給底層文件系統的函數,底層文件系統根據這些參數來執行具體的操作 。底層文件系統在完成操作后,會將結果返回給 VFS,VFS 再將結果返回給應用程序。

四、VFS與其他內核組件的關系

4.1與進程管理的關聯

在 Linux 系統中,進程是資源分配和調度的基本單位,而文件操作是進程運行過程中常見的行為之一。進程與 VFS 之間存在著緊密的聯系,這種聯系主要體現在進程對文件的各種操作上,比如打開文件、讀取文件、寫入文件、關閉文件等 。當進程進行這些文件操作時,它并不是直接與底層的文件系統打交道,而是通過 VFS 提供的統一接口來完成。這就好比進程是一個顧客,它只需要告訴 VFS 這個 “服務員” 自己想要進行什么樣的文件操作,VFS 就會去協調底層的文件系統來滿足進程的需求 。

以進程打開文件為例,當一個進程調用open函數打開一個文件時,VFS 會在后臺進行一系列復雜的操作。首先,VFS 會根據進程提供的文件路徑,在目錄項高速緩存(dentry cache)中查找對應的目錄項。如果目錄項不在緩存中,VFS 就會從磁盤上讀取目錄項信息,并將其加入到緩存中。通過目錄項,VFS 可以找到對應的索引節點(inode) 。索引節點中包含了文件的各種元數據,如文件的大小、權限、所有者、創建時間、修改時間、數據塊位置信息等。如果索引節點不在內存中,VFS 會從磁盤上讀取該索引節點并將其加載到內存中 。

接下來,VFS 會為打開的文件創建一個文件對象。文件對象中包含了指向索引節點的指針、當前文件的讀寫位置、文件操作的狀態標志以及指向文件操作函數集的指針等信息 。這個文件對象就像是進程與文件之間的 “橋梁”,進程通過文件對象來對文件進行后續的操作。同時,進程的task_struct結構體中包含一個files_struct結構體,files_struct結構體中維護著一個文件描述符表,文件描述符表中的每一項都指向一個打開的文件對象 。通過這種方式,進程可以方便地管理自己打開的文件。

在這個過程中,我們可以看到 VFS 起到了關鍵的作用。它不僅為進程提供了統一的文件操作接口,使得進程無需關心底層文件系統的具體實現細節,還負責管理文件系統相關的數據結構,如目錄項、索引節點、文件對象等,確保文件操作的順利進行 。同時,VFS 與進程管理之間的緊密協作也體現了 Linux 內核設計的精妙之處,各個組件之間相互配合,共同為系統的高效運行提供保障 。

4.2在 Linux 內核架構中的位置

為了更直觀地理解 VFS 在 Linux 內核中的地位,我們來看一下 Linux 內核架構圖:

圖片圖片

從圖中可以清晰地看到,VFS 處于用戶空間和各種具體文件系統之間,是連接兩者的關鍵橋梁 。用戶空間的應用程序通過系統調用接口(System Call Interface)與內核進行交互,而 VFS 則負責處理這些系統調用,并將其轉發到底層的具體文件系統 。

在 Linux 系統中,“一切皆文件” 的理念深入人心,而 VFS 正是這一理念的重要體現。它將不同類型的文件系統,如基于磁盤的文件系統(如ext4、XFS 等)、網絡文件系統(如 NFS、CIFS 等)、虛擬文件系統(如 /proc、/sys 等),都統一抽象成可以通過文件操作接口(如open、close、read、write 等)訪問的對象 。這使得應用程序可以使用統一的方式來操作不同類型的文件系統,大大提高了系統的通用性和可擴展性 。

例如,當應用程序調用read函數讀取文件內容時,這個請求首先會通過系統調用接口進入內核空間,然后由 VFS 接收 。VFS 根據文件的路徑信息,確定該文件所屬的具體文件系統,并將read請求轉發給對應的文件系統驅動程序 。文件系統驅動程序根據 VFS 傳遞的參數,在磁盤或其他存儲設備上讀取相應的數據,并將數據返回給 VFS 。VFS 再將數據返回給應用程序,完成整個文件讀取操作 。

VFS 在 Linux 內核架構中的核心位置,使其成為了文件系統管理的關鍵組件。它不僅為用戶空間提供了統一的文件訪問接口,還協調了不同文件系統之間的工作,確保了 Linux 系統在文件管理方面的高效性和靈活性 。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2024-02-02 10:38:06

虛擬文件系統VFS

2019-05-22 09:00:16

Linux虛擬文件系統

2019-05-29 16:33:32

Linux虛擬系統

2022-01-14 08:39:47

鴻蒙HarmonyOS應用

2020-07-22 14:53:06

Linux系統虛擬文件

2019-09-20 10:04:45

Linux系統虛擬文件

2018-08-24 10:10:25

Linux文件系統技術

2023-12-06 09:32:35

Linux系統

2009-07-21 10:49:26

ASP.NET虛擬文件

2025-04-08 04:00:00

Linux內核頁面回收

2022-04-21 14:09:17

lsofLinux虛擬文件

2020-10-12 17:40:44

lsofLinux虛擬文件

2010-03-02 14:21:30

Linux操作系統

2019-06-14 14:58:58

虛擬文件系統Linux

2021-08-24 10:57:24

Linux文件系統內存

2017-04-12 14:30:45

Linux內核DebugFS

2017-03-30 10:13:11

Linux內核文件系統

2017-02-06 16:18:57

微軟GitGVFS

2010-01-21 09:15:05

Linux嵌入式文件系

2024-08-28 12:13:35

點贊
收藏

51CTO技術棧公眾號

亚洲香蕉网站| 色久综合一二码| 精品国产一区二区三区四区vr | 99久久国产宗和精品1上映| 久久精品三级| 国产一区二区色| 色天下一区二区三区| 国产亚洲美女久久| caoprom在线| 日韩精品一区二区三区在线| 国模吧精品人体gogo| 亚洲人精品午夜| 91插插插插插插插插| 国产免费xxx| 99在线|亚洲一区二区| 川上优av一区二区线观看| 亚洲人成网77777色在线播放 | 欧美极品少妇全裸体| 91国产一区| 欧美精品少妇videofree| 国产剧情一区二区在线观看| 一区二区国产精品视频| 免费观看亚洲| 在线日韩第一页| 亚洲伦乱视频| 久久精品电影网| 大香伊人久久精品一区二区| 97在线精品视频| 欧美理论在线播放| 国产综合香蕉五月婷在线| 欧美激情一区| 欧美日韩国产天堂| 第一福利在线| 精品视频123区在线观看| 在线观看免费黄色| 欧美va亚洲va香蕉在线| 大菠萝精品导航| 精品国内亚洲在观看18黄| 国产精品传媒| 国产欧洲精品视频| 国产精品日韩| 国产日韩亚洲欧美在线| 国产亚洲精品7777| av线上观看| 欧美少妇bbb| a√中文在线观看| www国产精品视频| 国产精品45p| 91日韩在线播放| 麻豆精品在线播放| 国产免费黄色小视频| 最新不卡av在线| 麻豆网在线观看| www.欧美三级电影.com| 国产精品探花在线观看| 欧美激情第六页| 91免费看`日韩一区二区| 黄页网站在线播放| 亚洲国内精品在线| 日本在线中文字幕一区| 国产亚洲精品久久飘花| 国产成人精品一区二区三区在线| 久久九九国产精品怡红院| 日韩欧美天堂| 免费看国产精品一二区视频| 99精品久久99久久久久| 在线观看黄色小视频| 亚洲第一免费网站| 国产一区二区三区亚洲| 国产乱码精品一区二区三区不卡| 国产在线精品视频| 美乳在线观看| 亚洲精品综合精品自拍| 欧美美乳视频| 精品日韩在线播放| 婷婷一区二区三区| 四虎4545www精品视频| 成人免费午夜电影| www.av精品| 色噜噜色狠狠狠狠狠综合色一| 国产一区美女在线| 在线视频资源站| www.色综合| 国产色综合网| 黑人巨大精品欧美一区二区奶水| 精品国产伦一区二区三区观看体验| 免费福利视频一区| 天天成人综合网| 精品久久久久久| 国产aa精品| 性欧美.com| 偷拍日韩校园综合在线| 91精品麻豆| 青娱乐国产91| 性做久久久久久久久| 成人污版视频| 亚洲一区二区三区免费观看| 精品国产乱码久久久久酒店| 国产精品毛片aⅴ一区二区三区| 国产中文一区二区| 亚洲日韩欧美一区二区在线| 欧洲av不卡| 九色91国产| 亚洲一区二区四区蜜桃| 台湾天天综合人成在线| 亚洲精品8mav| 欧美伊人久久大香线蕉综合69 | 日韩精品中文字幕一区| 欧美日韩中字| 国产喷水theporn| 亚洲午夜av久久乱码| 视频一区视频二区中文字幕| 最新亚洲伊人网| 久久久日本电影| 成人黄色av电影| 欧美videossex另类| 欧美日韩一区三区四区| 欧美黄色录像| 久久久噜噜噜www成人网| 欧美sm极限捆绑bd| 99日韩精品| 91xxx在线观看| 91视频婷婷| 精品国产乱码久久久久久虫虫漫画| 少妇精品久久久| 国产免费又粗又猛又爽| 欧美成人激情视频免费观看| 国产成人精品亚洲日本在线桃色| 国产蜜臀一区二区打屁股调教| 国产精品一区二区三区四区五区| 日韩欧美中文字幕在线播放| 日韩理论电影大全| 亚洲女优视频| 5g影院天天爽成人免费下载| 在线看一区二区| 激情亚洲网站| 成人在线网址| 正在播放国产精品| 国产一区二区三区网站| 成人免费毛片嘿嘿连载视频| 国产精品亚洲欧美一级在线| 天堂一区在线观看| 国产精品日韩欧美大师| 欧美午夜性色大片在线观看| 亚洲夜间福利| 男人天堂亚洲天堂| 欧美人成在线观看| 久久久久久久久久久久久久久久久久av | 亚洲国产精品一区二区三区| 美女视频黄 久久| 成人片免费看| 黄色a级片免费| 欧美亚洲第一页| 香蕉av福利精品导航| 国产一区二区三区四区三区四| 黄色网页在线播放| 在线观看亚洲视频啊啊啊啊| 国产亚洲欧洲高清一区| 99国产精品久久久久久久久久久| 国产成人免费av一区二区午夜| 欧美日韩激情视频在线观看| 91av视频在线观看| 污片在线观看一区二区| 天天做天天爱天天综合网2021| 日韩伦理在线观看| 亚洲一区二区三区色| 麻豆乱码国产一区二区三区| 亚洲免费电影在线| 妖精视频成人观看www| 午夜精品成人av| 国产乱真实合集| 欧美国产综合视频| 最近2019中文字幕mv免费看 | 久久久久久久久久久福利| 欧美国产第一页| 色婷婷精品久久二区二区蜜臀av| 日本91福利区| 1313精品午夜理伦电影| 三级视频在线| 99中文字幕在线观看| 久久久久久12| 欧美日韩一级片在线观看| 丰满白嫩尤物一区二区| 国内精品伊人久久久| a'aaa级片在线观看| 黄色av资源| 欧美精品中文字幕一区二区| 日韩视频一区在线| 欧美日韩一区二区免费在线观看| 久久电影国产免费久久电影| 九热爱视频精品视频| 成人免费图片免费观看| 成人在线播放网站| 日韩欧美三级一区二区| 97在线观看视频| 亚洲国产另类 国产精品国产免费| 亚洲免费观看视频| 久久激情五月婷婷| 天天色综合色| japansex久久高清精品|