0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

介绍虚拟文件系统的原理与实现

Linux爱好者 来源:Linux内核那些事 2023-02-02 10:01 次阅读

在 Unix 的世界里,有句很经典的话:一切对象皆是文件。这句话的意思是说,可以将 Unix 操作系统中所有的对象都当成文件,然后使用操作文件的接口来操作它们。Linux 作为一个类 Unix 操作系统,也努力实现这个目标。

虚拟文件系统简介

为了实现一切对象皆是文件这个目标,Linux 内核提供了一个中间层:虚拟文件系统(Virtual File System)。

如果大家使用过面向对象编程语言(如C++/Java等)的话,应该对接口这个概念并不陌生。而虚拟文件系统类似于面向对象中的接口,定义了一套标准的接口。开发者只需要实现这套接口,即可以使用操作文件的接口来操作对象。如下图所示:

88541544-a233-11ed-bfe3-dac502259ad0.jpg

上图中的蓝色部分就是虚拟文件系统所在位置。

从上图可以看出,虚拟文件系统为上层应用提供了统一的接口。如果某个文件系统实现了虚拟文件系统的接口,那么上层应用就能够使用诸如open()、read()和write()等函数来操作它们。

今天,我们就来介绍虚拟文件系统的原理与实现。

虚拟文件系统原理

在阐述虚拟文件系统的原理前,我们先来介绍一个 Java 例子。通过这个 Java 例子,我们能够更容易理解虚拟文件系统的原理。

一个Java例子

如果大家使用过 Java 编写程序的话,那么就很容易理解虚拟文件系统了。我们使用 Java 的接口来模拟虚拟文件系统的定义:

publicinterfaceVFSFile{
intopen(Stringfile,intmode);
intread(intfd,byte[]buffer,intsize);
intwrite(intfd,byte[]buffer,intsize);
...
}

上面定义了一个名为VFSFile的接口,接口中定义了一些方法,如open()、read()和write()等。现在我们来定义一个名为Ext3File的对象来实现这个接口:

publicclassExt3FileimplementsVFSFile{
@Override
publicintopen(Stringfile,intmode){
...
}

@Override
publicintread(intfd,byte[]buffer,intsize){
...
}

@Override
publicintwrite(intfd,byte[]buffer,intsize){
...
}

...
}

现在我们就能使用VFSFile接口来操作Ext3File对象了,如下代码:

publicclassMain(){
publicstaticvoidmain(String[]args){
VFSFilefile=newExt3File();

intfd=file.open("/tmp/file.txt",0);
...
}
}

从上面的例子可以看出,底层对象只需要实现VFSFile接口,就可以使用VFSFile接口相关的方法来操作对象,用户完全不需要了解底层对象的实现过程。

虚拟文件系统原理

上面的 Java 例子已经大概说明虚拟文件系统的原理,但由于 Linux 是使用 C 语言来编写的,而 C 语言并没有接口这个概念。所以,Linux 内核使用了一些技巧来模拟接口这个概念。

下面来介绍一下 Linux 内核是如何实现的。

1. file结构

为了模拟接口,Linux 内核定义了一个名为file的结构体,其定义如下:

structfile{
...
conststructfile_operations*f_op;
...
};

在 file 结构中,最为重要的一个字段就是f_op,其类型为file_operations结构。而file_operations结构是由一组函数指针组成,其定义如下:

structfile_operations{
...
loff_t(*llseek)(structfile*,loff_t,int);
ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);
ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*);
...
int(*open)(structinode*,structfile*);
...
};

从file_operations结构的定义可以隐约看到接口的影子,所以可以猜想出,如果实现了file_operations结构中的方法,应该就能接入到虚拟文件系统中。

在 Linux 内核中,file结构代表着一个被打开的文件。所以,只需要将file结构的f_op字段设置成不同文件系统实现好的方法集,那么就能够使用不同文件系统的功能。

这个过程在__dentry_open()函数中实现,如下所示:

staticstructfile*
__dentry_open(structdentry*dentry,
structvfsmount*mnt,
tructfile*f,
int(*open)(structinode*,structfile*),
conststructcred*cred)
{
...
inode=dentry->d_inode;
...
//设置file结构的f_op字段为底层文件系统实现的方法集
f->f_op=fops_get(inode->i_fop);
...
returnf;
}

设置好file结构的f_op字段后,虚拟文件系统就能够使用通用的接口来操作此文件了。调用过程如下:

8863a5cc-a233-11ed-bfe3-dac502259ad0.png

2. file_operations结构

底层文件系统需要实现虚拟文件系统的接口,才能被虚拟文件系统使用。也就是说,底层文件系统需要实现file_operations结构中的方法集。

一般底层文件系统会在其内部定义好file_operations结构,并且填充好其方法集中的函数指针。如minix文件系统就定义了一个名为minix_file_operations的file_operations结构。其定义如下:

//文件:fs/minix/file.c

conststructfile_operationsminix_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结构。如下图所示:

887c2a02-a233-11ed-bfe3-dac502259ad0.png

可以看到,file结构有个指向dentry结构的指针,如下所示:

structfile{
...
structpathf_path;
...
conststructfile_operations*f_op;
...
};

structpath{
...
structdentry*dentry;
};

与文件类似,目录也有相关的操作接口,所以在dentry结构中也有操作方法集,如下所示:

structdentry{
...
structdentry*d_parent;//父目录指针
structqstrd_name;//目录名字
structinode*d_inode;//指向inode结构
...
conststructdentry_operations*d_op;//操作方法集
...
};

其中的d_op字段就是目录的操作方法集。

内核在打开文件时,会为路径中的每个目录创建一个dentry结构,并且使用d_parent字段来指向其父目录项,这样就能通过d_parent字段来追索到根目录。

4. inode结构

在 Linux 内核中,inode结构表示一个真实的文件。为什么有了dentry结构还需要inode结构呢?这是因为 Linux 存在硬链接的概念。

例如使用以下命令为/usr/local/lib/libc.so文件创建一个硬链接:

ln/usr/local/lib/libc.so/tmp/libc.so

现在/usr/local/lib/libc.so和/tmp/libc.so指向同一个文件,但它们的路径是不一样的。所以,就需要引入inode结构了。如下图所示:

888c689a-a233-11ed-bfe3-dac502259ad0.png

由于/usr/local/lib/libc.so和/tmp/libc.so指向同一个文件,所以它们都使用同一个inode对象。

inode 结构保存了文件的所有属性值,如文件的创建时间、文件所属用户和文件的大小等。其定义如下所示:

structinode{
...
uid_ti_uid;//文件所属用户
gid_ti_gid;//文件所属组
...
structtimespeci_atime;//最后访问时间
structtimespeci_mtime;//最后修改时间
structtimespeci_ctime;//文件创建时间
...
unsignedshorti_bytes;//文件大小
...
conststructfile_operations*i_fop;//文件操作方法集(用于设置file结构)
...
};

我们注意到 inode 结构有个类型为file_operations结构的字段i_fop,这个字段保存了文件的操作方法集。当用户调用open()系统调用打开文件时,内核将会使用inode结构的i_fop字段赋值给file结构的f_op字段。我们再来重温下赋值过程:

staticstructfile*
__dentry_open(structdentry*dentry,
structvfsmount*mnt,
tructfile*f,
int(*open)(structinode*,structfile*),
conststructcred*cred)
{
...
//文件对应的inode对象
inode=dentry->d_inode;
...
//使用inode结构的i_fop字段赋值给file结构的f_op字段
f->f_op=fops_get(inode->i_fop);
...
returnf;
}

总结

本文主要介绍了虚拟文件系统的基本原理,从分析中可以发现,虚拟文件系统使用了类似于面向对象编程语言中的接口概念。正是有了虚拟文件系统,Linux 才能支持各种各样的文件系统。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    102996
  • UNIX操作系统

    关注

    0

    文章

    13

    浏览量

    15261
  • C语言
    +关注

    关注

    180

    文章

    7533

    浏览量

    128783
  • LINUX内核
    +关注

    关注

    1

    文章

    311

    浏览量

    21389

原文标题:细说 Linux 虚拟文件系统原理

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux平台/proc虚拟文件系统详解

    Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc文件系统是一个伪文件系统(即虚拟文件系统),它只存在内存当中,而不占用外
    发表于 06-08 10:49 1082次阅读
    Linux平台/proc<b class='flag-5'>虚拟文件系统</b>详解

    Linux虚拟文件系统的基础知识

    虚拟文件系统是一个很庞大的架构,如果要分析的面面俱到,会显得特别复杂而笨拙,让人看着看着,就不知所云了(当然主要还是笔者太菜),所以这篇博客,以 open() 函数为切入点,来试着分析分析VFS文件系统的运转机理,本文的代码来源于 linux3.4.2。
    发表于 08-25 12:17 168次阅读
    Linux<b class='flag-5'>虚拟文件系统</b>的基础知识

    STM32F429 sdio虚拟文件系统的相关资料推荐

    SD卡虚拟文件系统是在我之前的SPI虚拟文件系统的基础上做的,所以只会介绍SD卡配置部分,DFS配置跟之前的一样就不详细介绍了。1.添加文件
    发表于 12-13 06:02

    VFS虚拟文件系统描述

    1.VFS——虚拟文件系统,是文件系统对外的接口2.cache——高速缓冲存储器3.linux的每个文件都是由 i 节点的结构体表示,i 节点包含对文件的描述:
    发表于 12-22 06:56

    如何将CAN设备挂载到DFS虚拟文件系统上通过select来监听CAN设备?

    我想问一下 我是否可以将CAN设备挂载到DFS虚拟文件系统上,获取CAN设备的文件描述符后,再通过select来监听CAN设备?
    发表于 05-13 10:48

    Linux虚拟文件系统实现技术探讨

    文章论述了 Linux 文件系统的逻辑关系和逻辑结构,对VFS 中几个主要的数据结构进行了分析,剖析了Linux 文件系统 中一个物理文件系统的安装与注册、VFS的产生,以及通过VFS管理和访问
    发表于 06-08 17:51 32次下载
    Linux<b class='flag-5'>虚拟文件系统</b><b class='flag-5'>实现</b>技术探讨

    Xilinx Zynq制作修改根文件系统的方法

    proc文件系统是用来提供内核和进程信息的虚拟文件系统,使用内核自动生成的文件,加载完成一定要能查到很多信息才对。
    发表于 07-13 08:31 3187次阅读

    linux 虚拟文件可以系统实现

    虚拟文件系统(VFS)是linux内核和具体I/O设备之间的封装的一层共通访问接口,通过这层接口,linux内核可以以同一的方式访问各种I/O设备。
    发表于 05-04 16:56 378次阅读
    linux <b class='flag-5'>虚拟文件</b>可以<b class='flag-5'>系统</b><b class='flag-5'>实现</b>

    嵌入式Linux常用文件系统

    Linux支持很多文件系统,在选择时应根据应用的功能选择文件系统 内核只认识VFS(虚拟文件系统),不同的文件系统实现的都是和VFS的
    发表于 05-04 17:19 2148次阅读
    嵌入式Linux常用<b class='flag-5'>文件系统</b>

    简单介绍Linux虚拟文件系统–VFS

    Linux中可以支持多种文件系统,而且支持各种文件系统之间相互访问,这是因为有一个虚拟文件系统虚拟文件系统也叫虚拟文件系统转换(Virtu
    发表于 04-24 14:35 1007次阅读

    linux文件系统中的虚拟文件系统设计详解

    Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等。通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体
    发表于 04-02 14:37 1585次阅读
    linux<b class='flag-5'>文件系统</b>中的<b class='flag-5'>虚拟文件系统</b>设计详解

    如何区别Linux文件系统呢?

    虚拟文件系统是一种神奇的抽象,它使得 “一切皆文件” 哲学在 Linux 中成为了可能。
    的头像 发表于 08-09 18:00 3409次阅读

    深入剖析Linux内核虚拟文件系统

    虚拟文件系统(Virtual File System,简称VFS)是Linux内核的子系统之一,它为用户程序提供文件文件系统操作的统一接口,屏蔽不同
    的头像 发表于 05-14 15:53 2739次阅读
    深入剖析Linux内核<b class='flag-5'>虚拟文件系统</b>

    RT-Thread文档_虚拟文件系统

    RT-Thread文档_虚拟文件系统
    发表于 02-22 18:42 1次下载
    RT-Thread文档_<b class='flag-5'>虚拟文件系统</b>

    鸿蒙轻内核源码分析:虚拟文件系统 VFS

    VFS(Virtual File System)是文件系统虚拟层,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类 Unix
    的头像 发表于 02-18 14:50 136次阅读