在 Unix 的世界中,有一句經典的話:一切皆文件。這句話的意思是,在 Unix 作業系統中,所有的物件都可以被視為文件,並使用操作文件的介面來操作它們。作為一個類別 Unix 作業系統,Linux 也努力實現這個目標。
虛擬檔案系統簡介
#為了實現 一切皆檔案
這個目標,Linux 核心提供了一個中間層:虛擬檔案系統(Virtual File System)
。
如果您曾經使用過物件導向程式語言(如 C /Java 等),那麼您應該對 介面
這個概念並不陌生。虛擬檔案系統類似於物件導向程式設計中的接口,它定義了一套標準的介面。開發人員只需實現這套接口,就可以使用操作文件的接口來操作對象。如下圖所示:

上圖中的藍色部分就是虛擬檔案系統所在位置。
從上圖可以看出,虛擬檔案系統為上層應用提供了統一的介面。如果某個檔案系統實作了虛擬檔案系統的接口,那麼上層應用程式就能夠使用諸如open()
、read()
和write()
等函數來操作它們。
今天,我們就來介紹虛擬檔案系統的原理與實作。
虛擬檔案系統原理
#在闡述虛擬檔案系統的原理前,我們先來介紹一個 Java 範例。透過這個 Java 例子,我們能夠更容易理解虛擬檔案系統的原理。
一個Java範例
#如果大家使用過 Java 寫程式的話,那就很容易理解虛擬檔案系統了。我們使用 Java 的介面來模擬虛擬檔案系統的定義:
public interface VFSFile { int open(String file, int mode); int read(int fd, byte[] buffer, int size); int write(int fd, byte[] buffer, int size); ... }
上面定義了一個名為VFSFile
的接口,接口中定義了一些方法,如open()
、read()
和 write()
等。現在我們來定義一個名為 Ext3File
的物件來實作這個介面:
public class Ext3File implements VFSFile { @Override public int open(String file, int mode) { ... } @Override public int read(int fd, byte[] buffer, int size) { ... } @Override public int write(int fd, byte[] buffer, int size) { ... } ... }
現在我們就能使用 VFSFile
介面來操作 Ext3File
物件了,如下程式碼:
public class Main() { public static void main(String[] args) { VFSFile file = new Ext3File(); int fd = file.open("/tmp/file.txt", 0); ... } }
从上面的例子可以看出,底层对象只需要实现 VFSFile
接口,就可以使用 VFSFile
接口相关的方法来操作对象,用户完全不需要了解底层对象的实现过程。
虚拟文件系统原理
上面的 Java 例子已经大概说明虚拟文件系统的原理,但由于 Linux 是使用 C 语言来编写的,而 C 语言并没有接口这个概念。所以,Linux 内核使用了一些技巧来模拟接口这个概念。
下面来介绍一下 Linux 内核是如何实现的。
1. file结构
为了模拟接口,Linux 内核定义了一个名为 file
的结构体,其定义如下:
struct file { ... const struct file_operations *f_op; ... };
在 file 结构中,最为重要的一个字段就是 f_op
,其类型为 file_operations
结构。而 file_operations
结构是由一组函数指针组成,其定义如下:
struct file_operations { ... loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ... int (*open) (struct inode *, struct file *); ... };
从 file_operations
结构的定义可以隐约看到接口的影子,所以可以猜想出,如果实现了 file_operations
结构中的方法,应该就能接入到虚拟文件系统中。
在 Linux 内核中,file
结构代表着一个被打开的文件。所以,只需要将 file
结构的 f_op
字段设置成不同文件系统实现好的方法集,那么就能够使用不同文件系统的功能。
这个过程在 __dentry_open()
函数中实现,如下所示:
static struct file * __dentry_open(struct dentry *dentry, struct vfsmount *mnt, truct file *f, int (*open)(struct inode *, struct file *), const struct cred *cred) { ... inode = dentry->d_inode; ... // 设置file结构的f_op字段为底层文件系统实现的方法集 f->f_op = fops_get(inode->i_fop); ... return f; }
设置好 file
结构的 f_op
字段后,虚拟文件系统就能够使用通用的接口来操作此文件了。调用过程如下:

2. file_operations结构
底层文件系统需要实现虚拟文件系统的接口,才能被虚拟文件系统使用。也就是说,底层文件系统需要实现 file_operations
结构中的方法集。
一般底层文件系统会在其内部定义好 file_operations
结构,并且填充好其方法集中的函数指针。如 minix文件系统
就定义了一个名为 minix_file_operations
的 file_operations
结构。其定义如下:
// 文件:fs/minix/file.c const struct file_operations minix_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .aio_read = generic_file_aio_read, .write = do_sync_write, .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .fsync = generic_file_fsync, .splice_read = generic_file_splice_read, };
也就是说,如果当前使用的是 minix 文件系统,当使用 read()
函数读取其文件的内容时,那么最终将会调用 do_sync_read()
函数来读取文件的内容。
3. dentry结构
到这里,虚拟文件系统的原理基本分析完毕,但还有两个非常重要的结构要介绍一下的:dentry
和 inode
。
dentry
结构表示一个打开的目录项,当我们打开文件 /usr/local/lib/libc.so
文件时,内核会为文件路径中的每个目录创建一个 dentry
结构。如下图所示:

由于 /usr/local/lib/libc.so
和 /tmp/libc.so
指向同一个文件,所以它们都使用同一个 inode
对象。
inode 结构保存了文件的所有属性值,如文件的创建时间、文件所属用户和文件的大小等。其定义如下所示:
struct inode { ... uid_t i_uid; // 文件所属用户 gid_t i_gid; // 文件所属组 ... struct timespec i_atime; // 最后访问时间 struct timespec i_mtime; // 最后修改时间 struct timespec i_ctime; // 文件创建时间 ... unsigned short i_bytes; // 文件大小 ... const struct file_operations *i_fop; // 文件操作方法集(用于设置file结构) ... };
我们注意到 inode 结构有个类型为 file_operations
结构的字段 i_fop
,这个字段保存了文件的操作方法集。当用户调用 open()
系统调用打开文件时,内核将会使用 inode
结构的 i_fop
字段赋值给 file
结构的 f_op
字段。我们再来重温下赋值过程:
static struct file * __dentry_open(struct dentry *dentry, struct vfsmount *mnt, truct file *f, int (*open)(struct inode *, struct file *), const struct cred *cred) { ... // 文件对应的inode对象 inode = dentry->d_inode; ... // 使用inode结构的i_fop字段赋值给file结构的f_op字段 f->f_op = fops_get(inode->i_fop); ... return f; }
总结
本文主要介绍了 虚拟文件系统
的基本原理,从分析中可以发现,虚拟文件系统使用了类似于面向对象编程语言中的接口概念。正是有了 虚拟文件系统
,Linux 才能支持各种各样的文件系统。
以上是細說 Linux 虛擬檔案系統原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

介紹 Linux是一個強大的操作系統,由於其靈活性和效率,開發人員,系統管理員和電源用戶都喜歡。但是,經常使用長而復雜的命令可能是乏味的

Linux適用於服務器、開發環境和嵌入式系統。 1.作為服務器操作系統,Linux穩定高效,常用於部署高並發應用。 2.作為開發環境,Linux提供高效的命令行工具和包管理系統,提升開發效率。 3.在嵌入式系統中,Linux輕量且可定制,適合資源有限的環境。

簡介:通過基於Linux的道德黑客攻擊數字邊界 在我們越來越相互聯繫的世界中,網絡安全至關重要。 道德黑客入侵和滲透測試對於主動識別和減輕脆弱性至關重要

Linux基礎學習從零開始的方法包括:1.了解文件系統和命令行界面,2.掌握基本命令如ls、cd、mkdir,3.學習文件操作,如創建和編輯文件,4.探索高級用法如管道和grep命令,5.掌握調試技巧和性能優化,6.通過實踐和探索不斷提陞技能。

Linux在服務器、嵌入式系統和桌面環境中的應用廣泛。 1)在服務器領域,Linux因其穩定性和安全性成為託管網站、數據庫和應用的理想選擇。 2)在嵌入式系統中,Linux因其高度定制性和高效性而受歡迎。 3)在桌面環境中,Linux提供了多種桌面環境,滿足不同用戶需求。

Linux的缺點包括用戶體驗、軟件兼容性、硬件支持和學習曲線。 1.用戶體驗不如Windows或macOS友好,依賴命令行界面。 2.軟件兼容性不如其他系統,缺乏許多商業軟件的原生版本。 3.硬件支持不如Windows全面,可能需要手動編譯驅動程序。 4.學習曲線較陡峭,掌握命令行操作需要時間和耐心。

Linuxisnothardtolearn,butthedifficultydependsonyourbackgroundandgoals.ForthosewithOSexperience,especiallycommand-linefamiliarity,Linuxisaneasytransition.Beginnersmayfaceasteeperlearningcurvebutcanmanagewithproperresources.Linux'sopen-sourcenature,bas

Linux的五個基本組件是:1.內核,管理硬件資源;2.系統庫,提供函數和服務;3.Shell,用戶與系統交互的接口;4.文件系統,存儲和組織數據;5.應用程序,利用系統資源實現功能。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Atom編輯器mac版下載
最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

WebStorm Mac版
好用的JavaScript開發工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。