Linux-虚拟文件系统 - STEMHA's Blog

Linux-虚拟文件系统

linux设计思想

Linux作为一个最著名的自由软件,几乎处处体现了“自由”的思想,你可以编译适合自己系统要求的内核,或者轻松添加别人开发的新的模块。只要你有实力,你还可以自己写一个新的Linux 支持的文件系统。
Linux 不仅支持多种文件系统,而且还支持这些文件系统相互之间进行访问。Linux成功的关键因素之一是它具有与其他操作系统和谐共存的能力,你能够透明的安装具有其他操作系统文件格式的磁盘分区(比如Windows系统)。这一切都要归功于神奇的虚拟文件系统。

虚拟文件系统思想

虚拟文件系统所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核;其中有一个字段或函数来支持linux所支持的所有文件系统所提供的任何操作。
对所调用的每个读、写或其他函数,内核都能把他们替换成支持本地linux文件系统、NTFS文件系统或者文件所在的其他任何文件系统的实际函数。

我们需要知道什么?

概括的说,本文主要讲虚拟文件系统的设计目标,结构及其实现:

  • 虚拟文件系统是什么?为什么要使用虚拟文件系统?怎么实现虚拟文件系统的?
  • 虚拟文件系统的组成有哪些,在linux中处于什么样的层次,能不能画个原理图示意一下?
  • Linux中虚拟文件系统、磁盘/Flash文件系统及一般的设备文件与设备驱动程序之间的关系是什么样子的?
  • Linux文件操作的系统调用和C库文件操作的相关介绍
  • sysfs文件系统与Linux设备模型是什么?
  • linux文件系统中关键的结构体的介绍,inode结构体与file结构体

虚拟文件系统概念

虚拟文件系统又称虚拟文件系统转换(Virual Filesystem Switch ,简称VFS):

  • 说它虚拟,是因为它所有的数据结构都是在运行以后才建立,并在卸载时删除,而在磁盘上并没有存储这些数据结构。
  • 如果只有VFS,系统是无法工作的,因为它的这些数据结构不能凭空而来,只有与实际的文件系统,如Ext2、Minix、MSDOS、VFAT 等相结合,才能开始工作,所以VFS 并不是一个真正的文件系统。
  • 与VFS 相对应,我们称Ext2、Minix、MSDOS 等为具体文件系统
  • 是内核的一个软件层,用来处理与Unix标准文件系统相关的所有系统调用,也为各种文件系统提供一个通用的接口。

VFS 的作用

概括说来,VFS 主要有以下几个作用。

  1. 对具体文件系统的数据结构进行抽象,以一种统一的数据结构进行管理。
  2. 接受用户层的系统调用,例如write、open、stat、link 等。
  3. 支持多种具体文件系统之间相互访问。
  4. 接受内核其他子系统的操作请求,特别是内存管理子系统。
  • VFS 提供一个统一的接口(实际上就是file_operatoin 数据结构),一个具体文件系统要想被Linux 支持,就必须按照这个接口编写自己的操作函数,而将自己的细节
    对内核其他子系统隐藏起来。
  • 因而,对内核其他子系统以及运行在操作系统之上的用户程序而言,所有的文件系统都是一样的。实际上,要支持一个新的文件系统,主要任务就是编写这些接口函数。
图1. Linux虚拟文件系统与整个软硬件系统的关系

文件系统的逻辑关系

VFS 称为内核的一个子系统,其他子系统只与VFS 打交道,而并不与具体文件系统发生联系。对具体文件系统来说,VFS 是一个管理者,而
对内核的其他子系统来说,VFS 是它们与具体文件系统的一个接口,整个Linux 中文件系统的逻辑关系如图2所示。

图2. Linux中文件系统的逻辑关系示意图

文件系统与设备驱动之间的关系

Linux中虚拟文件系统、磁盘/Flash文件系统及一般的设备文件与设备驱动程序之间的关系。

图3. 文件系统与设备驱动之间的关系

应用程序和VFS之间的接口是系统调用,而VFS与文件系统以及设备文件之间的接口是file_operations结构体成员函数,这个结构体包含对文件进行打开、关闭、读写、控制的一系列成员函数

由于字符设备的上层没有类似于磁盘的ext2等文件系统,所以字符设备的file_operations成员函数就直接由设备驱动提供了。

块设备有两种访问方法

  • 一种方法是不通过文件系统直接访问裸设备
    • 在Linux内核实现了统一的def_blk_fops这一file_operations,它的源代码位于fs/block_dev.c,所以当我们运行类似于“dd if=/dev/sdb1of=sdb1.img”的命令
    • 把整个/dev/sdb1裸分区复制到sdb1.img的时候,内核走的是def_blk_fops这个file_operations;
  • 另外一种方法是通过文件系统来访问块设备
    • file_operations的实现则位于文件系统内,文件系统会把针对文件的读写转换为针对块设备原始扇区的读写。
    • ext2、fat、Btrfs等文件系统中会实现针对VFS的file_operations成员函数,设备驱动层将看不到file_operations的存在。
图4. 应用程序、VFS与设备驱动

VFS支持的文件系统

VFS支持的文件系统可以划分为三种主要类型:

  • 这些文件系统管理在本地磁盘分区中可用的存储空间或者其他可以起到磁盘作用的设备(比如USB闪存)。
  • 这些文件系统允许轻易的访问属于其他网络计算机的文件系统所包含的文件。
  • 比如NFS,CIFS(用于微软Windows的通用网络系统)
  • 这些文件系统不管理本地或者远程磁盘空间。
  • 比如/proc、/sys、/dev等文件系统
  • VFS处理的系统调用

    VFS 处理的系统调用涉及文件系统、常规文件、目录及符号链接,还有一些特殊的系统调用,如下所示:

    • 涉及设备文件和管道文件的系统调用,诸如ioperm( )、ioctl( )、pipe( )和mknod( ),
    • 套接字系统调用,诸如socket( )、connect( )、bind( )和 protocols( )。

    VFS 的部分系统调用:

    点击展开系统调用列表 >folded
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    mount( )/ umount( )                                     安装/卸载文件系统
    sysfs( ) 获取文件系统信息
    statfs( )/ fstatfs( ) /ustat( ) 获取文件系统统计信息
    chroot( ) 更改根目录
    chdir( ) /fchdir( ) /getcwd( ) 更改当前目录
    mkdir( ) /rmdir( ) 创建/删除目录
    getdents( ) /readdir( )/ link( ) unlink( )/rename( ) 对目录项进行操作
    readlink( ) /symlink( ) 对软链接进行操作
    chown( ) /fchown( ) /lchown( ) 更改文件所有者
    chmod( )/ fchmod( ) /utime( ) 更改文件属性
    stat( ) /fstat( ) /lstat( ) access( ) 读取文件状态
    open( ) /close( ) /creat( ) /umask( ) 打开/关闭文件
    dup( ) /dup2( ) /fcntl( ) 对文件描述符进行操作
    select( ) /poll( ) 异步I/O 通信
    truncate( ) /ftruncate( ) 更改文件长度
    lseek( ) /_llseek( ) 更改文件指针
    read( )/ write( ) /readv( ) /writev( )/sendfile( ) 文件I/O 操作
    pread( )/ pwrite( ) 搜索并访问文件
    mmap( ) /munmap( ) 文件内存映射
    fdatasync( ) /fsync( ) /sync( )/ msync( ) 同步访问文件数据
    flock( ) 处理文件锁

    VFS 中的数据结构

    虚拟文件系统模型的实现方式:

    • 虚拟文件系统所隐含的主要思想在于引入了一个通用的文件模型,这个模型能够表示所有支持的文件系统。
    • 该模型严格遵守传统UNIX 文件系统提供的文件模型。
    • 你可以把通用文件模型看作是面向对象的,在这里,对象是一个软件结构,其中既定义了数据结构也定义了其上的操作方法。
    • 出于效率的考虑,Linux 的编码并未采用面向对象的程序设计语言(比如C++)。因此通用文件模型对象作为数据结构来实现:数据结构中指向函数的域就对应于对象的方法。

    通用文件模型由下列对象类型组成:

    • 超级块(superblock)对象:存放系统中已安装文件系统的有关信息。
      • 对于基于磁盘文件系统,这类对象通常对应于存放在磁盘上的文件系统控制块(filesystem control block),也就是说,每个文件系统都有一个超级块对象。
      • 很多具体文件系统中都有超级块结构,超级块是这些文件系统中最重要的数据结构,它是来描述整个文件系统信息的,是一个全局的数据结构。
      • 注意:Minix、Ext2 等有超级块,VFS 也有超级块,为了避免与后面介绍的Ext2 超级块发生混淆,这里用VFS 超级块来表示。
      • VFS 超级块是各种具体文件系统在安装时建立的,并在这些文件系统卸载时自动删除,可见,VFS 超级块确实只存在于内存中,同时
        提到VFS 超级块也应该说成是哪个具体文件系统的VFS超级块。
    • 索引节点(inode)对象:存放关于具体文件的一般信息。
      • 对于基于磁盘的文件系统,这类对象通常对应于存放在磁盘上的文件控制块(file control block),也就是说,每个文件都有一个索引节点对象。每个索引节点对象都有一个索引节点号,这个号唯一地标识某个文件系统中的指定文件。
      • 强调一点,具体文件系统的索引节点是存储在磁盘上的,是一种静态结构,要使用它,必须调入内存,填写VFS 的索引节点,因此,也称VFS索引节点动态节点
    • 目录项(dentry)对象:存放目录项与对应文件进行链接的信息。
      • 每个文件除了有一个索引节点inode 数据结构外,还有一个目录项dentry(directoryenrty)数据结构。dentry 结构中有个d_inode 指针指向相应的inode 结构。
      • VFS 把每个目录看作一个由若干子目录和文件组成的常规文件。例如,在查找路径名/tmp/test 时,内核为根目录“/”创建一个目录项对象,为根目录下的tmp 项创建一个第2 级目录项对象,为/tmp目录下的test 项创建一个第3 级目录项对象。
      • 每个磁盘文件系统都以自己特有的方式将该类信息存在磁盘上。
    • 文件(file)对象:存放打开文件与进程之间进行交互的有关信息。
      • 这类信息仅当进程访问文件期间存在于内存中。

    既然inode 结构和dentry 结构都是对文件各方面属性的描述,那为什么不把这两个结构“合二为一”呢?

    这是因为二者所描述的目标不同,dentry结构代表的是逻辑意义上的文件,所描述的是文件逻辑上的属性,因此,目录项对象在磁盘上并没有对应的映像;而inode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统(如Ext2),Ext2_ inode 结构在磁盘上就有对应的映像。所以说,一个索引节点对象可能对应多个目录项对象

    超级块、索引节点、目录项及文件的数据结构,它们的共同特点有两个:

    • 充分考虑到对多种具体文件系统的兼容性;
    • 是“虚”的,也就是说只能存在于内存。

    这正体现了VFS 的特点

    进程与VFS对象的交互

    示例

    下图是一个简单的示例,对进程与文件之间的交互过程进行了说明:

    • 三个不同的进程已经打开同一个文件,其中两个进程已经使用同一个硬链接。
    • 每个进程都使用自己的文件对象,但是因为两个进程共有硬链接的关系,我们只需要两个目录项对象,每个硬链接对应一个目录项对象。
    • 然后这两个目录项对象指向同一个索引节点对象,该索引节点对象标识超级块对象,以及随后的普通磁盘文件。
    进程与VFS对象的交互

    说明:

    • 最近最常使用的目录项对象被放在所谓目录项高速缓存的磁盘高速缓存中,以加速从文件路径名到最后一个路径分量的索引节点的转换过程

    磁盘高速缓存

    • 一般说来,磁盘高速缓存属于软件机制,它允许内核将原本存在磁盘上的某些信息保存在RAM中,以便对这些数据的进一步访问能快速进行,而不必慢速访问磁盘本身。
    • 除了目录项高速缓存,索引结点高速缓存之外,Linux还使用其他磁盘高速缓存,其中最重要的一种的页高速缓存。

    磁盘高速缓存,硬件高速缓存与内存高速缓存直接之间的区别

    硬件高速缓存是一个快速的静态的RAM,它加快了对慢速动态RAM的请求。
    内存高速缓存是一种软件机制,引入它是为了绕过内核内存分配器。
    与磁盘高速缓存不同,上述两者都与磁盘或其他设备无关。

    参考资料

    《Linux设备驱动开发详解:基于最新的Linux4.0内核》
    《深入分析Linux内核源代码》
    《深入理解Linux内核》

    评论

    Your browser is out-of-date!

    Update your browser to view this website correctly. Update my browser now

    ×