详解 Linux 中的虚拟文件系统


详解 Linux 中的虚拟文件系统

文章插图
 
虚拟文件系统是一种神奇的抽象,它使得 “一切皆文件” 哲学在 linux 中成为了可能 。
-- Alison Chariken(作者)
虚拟文件系统是一种神奇的抽象,它使得 “一切皆文件” 哲学在 Linux 中成为了可能 。
【详解 Linux 中的虚拟文件系统】什么是文件系统?根据早期的 Linux 贡献者和作家 Robert Love 所说,“文件系统是一个遵循特定结构的数据的分层存储 。” 不过,这种描述也同样适用于 VFAT( 虚拟文件分配表(Virtual File Allocation Table))、Git 和 Cassandra (一种 NoSQL 数据库 ) 。那么如何区别文件系统呢?
文件系统基础概念Linux 内核要求文件系统必须是实体,它还必须在持久对象上实现 open()、read() 和 write() 方法,并且这些实体需要有与之关联的名字 。从 面向对象编程 的角度来看,内核将通用文件系统视为一个抽象接口,这三大函数是“虚拟”的,没有默认定义 。因此,内核的默认文件系统实现被称为虚拟文件系统(VFS) 。
 
详解 Linux 中的虚拟文件系统

文章插图
 
如果我们能够 open()、read() 和 write(),它就是一个文件,如这个主控台会话所示 。
VFS 是著名的类 Unix 系统中 “一切皆文件” 概念的基础 。让我们看一下它有多奇怪,上面的小小演示体现了字符设备 /dev/console 实际的工作 。该图显示了一个在虚拟电传打字控制台(tty)上的交互式 Bash 会话 。将一个字符串发送到虚拟控制台设备会使其显示在虚拟屏幕上 。而 VFS 甚至还有其它更奇怪的属性 。例如,它 可以在其中寻址。
我们熟悉的文件系统如 ext4、NFS 和 /proc 都在名为 file_operations 的 C 语言数据结构中提供了三大函数的定义 。此外,个别的文件系统会以熟悉的面向对象的方式扩展和覆盖了 VFS 功能 。正如 Robert Love 指出的那样,VFS 的抽象使 Linux 用户可以轻松地将文件复制到(或复制自)外部操作系统或抽象实体(如管道),而无需担心其内部数据格式 。在用户空间这一侧,通过系统调用,进程可以使用文件系统方法之一 read() 从文件复制到内核的数据结构中,然后使用另一种文件系统的方法 write() 输出数据 。
属于 VFS 基本类型的函数定义本身可以在内核源代码的 fs/*.c 文件 中找到,而 fs/ 的子目录中包含了特定的文件系统 。内核还包含了类似文件系统的实体,例如 cgroup、/dev 和 tmpfs,在引导过程的早期需要它们,因此定义在内核的 init/ 子目录中 。请注意,cgroup、/dev 和 tmpfs 不会调用 file_operations 的三大函数,而是直接读取和写入内存 。
下图大致说明了用户空间如何访问通常挂载在 Linux 系统上的各种类型文件系统 。像管道、dmesg 和 POSIX 时钟这样的结构在此图中未显示,它们也实现了 struct file_operations,而且其访问也要通过 VFS 层 。
 
详解 Linux 中的虚拟文件系统

文章插图
How userspace accesses various types of filesyste
 
VFS 是个“垫片层”,位于系统调用和特定 file_operations 的实现(如 ext4 和 procfs)之间 。然后,file_operations 函数可以与特定于设备的驱动程序或内存访问器进行通信 。tmpfs、devtmpfs 和 cgroup 不使用 file_operations 而是直接访问内存 。
VFS 的存在促进了代码重用,因为与文件系统相关的基本方法不需要由每种文件系统类型重新实现 。代码重用是一种被广泛接受的软件工程最佳实践!唉,但是如果重用的代码 引入了严重的错误,那么继承常用方法的所有实现都会受到影响 。
/tmp:一个小提示找出系统中存在的 VFS 的简单方法是键入 mount | grep -v sd | grep -v :/,在大多数计算机上,它将列出所有未驻留在磁盘上,同时也不是 NFS 的已挂载文件系统 。其中一个列出的 VFS 挂载肯定是 /tmp,对吧?
 
详解 Linux 中的虚拟文件系统

文章插图
谁都知道把 /tmp 放在物理存储设备上简直是疯了!


    推荐阅读