Linux VFS

Posted by Max on December 6, 2014

概述

总体上说 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系 统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实体文件系统,例如 ext2,jffs 等。

简介

VFS是一种软件机制,全程不是大多数人想象的Virtual File System,而是Virtual Filesystem Switch, 翻译为虚拟文件交换系统。VFS负责Linux的文件系统的管理,所以更正式的叫法应该是Linux 的文件管理子系统。

与VFS有关的数据结构只存在于物理内存中,并不直接跟真正的磁盘文件有任何关系。这些数据结构在 使用时建立,不用时删除。也就是因为这样,才让Linux这棵“树”生动灵活。

基本数据结构

1. 超级块(superblock)对象

用于保存系统中已安装的文件系统信息。对于基于磁盘的实体文件系统,超级块对象一般对应于存放在 磁盘上的文件系统控制块。也就是说每个实体文件系统都应该有一个超级块对象。

2. 索引节点(inode)对象

用于保存具体文件的一般信息。对于基于磁盘的文件系统,索引节点对象一般对应于保存在磁盘中的文 件控制块(FCB)。也就是说,每个文件都应该有一个索引节点对象。每一个索引节点对象都有一个索引 节点号,用于唯一标识某个实体文件系统中的具体文件。

3. 目录项(dentry)对象

用于保存文件名、上级目录等信息,正是它形成了我们所看到的Linux这棵“树”。目录项对象完全是在 内存中的,会根据实际需要动态建立。

4. 文件(file)对象

用于保存已打开的文件与进程之间进行交互的信息。这类信息也是完全保存在内存中的,且仅当进程访 问文件期间有效。也就是说,当进程打开一个文件就会创建一个文件对象,当进程关闭文件,对应的文 件对象就会被释放。

实例

int main(int argc, char * argv[])
{
    FILE * fp = fopen("/usr/local/tmp/xx.txt", "rb");
    if(NULL == fp)
        return 0;
    char cBuffer[256];
    fread(cBuffer, 256, 1, fp);
    fclose(fp);
    return 0;
}

代码调用fopen读取文件,对应到系统中,是VFS调用文件驱动读取磁盘文件到内核,然后从内核态 拷贝到用户态。磁盘文件不是一蹴而就进入内核的,磁盘的特性决定了每一转读取512字节。从内 核态拷贝到用户态时受CPU控制,可以一次性完成。

当内核要访问一个文件的时候,第一步要做的是找到这个文件,将用户传进来的字符串表示的文件 路径转换成一个dentry结构,并建立好相应的inode和file结构,将指向file的描述符返回用户。 用户随后通过文件描述符,来访问这些数据结构。用户指定的文件路径会按绝对或相对路径初始化 查找路径为根目录或当前文件目录,然后按路径分隔符分成一系列小的内容进行查找,直到最后一 个分量是文件或者查找完成。如我们要找“/usr/local/tmp/xx.txt”这个文件,那么我们的文件 系统先初始化查找路径为根目录,然后查找分量usr,接着用usr的dentry->d_inode去找local, 这样循环到最后一个,最后找到“xx.txt”文件,核查inode权限成功后打开文件。注意,内核会缓 存找到的路径分量,所以往往只有第一次访问一个路径的时候,才会去访问磁盘,后面的访问会直 接从缓存里找。

参考

  1. 解析 Linux 中的 VFS 文件系统机制

  2. Linux内核源码阅读之打开文件篇