Linux虚拟文件系统简介
本文将对Linux下的VFS做一个简单介绍,主要包括VFS里面的一些概念,以及文件系统是如何与VFS交互的。
本文所涉及的代码摘自Linux-4.4.0-59
什么是VFS
VFS的全称为virtual File System(虚拟文件系统),可以把它理解为Linux下的文件系统平台。
对应用层来说,只要和VFS打交道就可以了,VFS对外提供了read,write等接口,应用层程序不需要关心底层具体的的文件系统是怎么实现的。
对具体的文件系统来说,VFS就是一个框架,提供了文件系统通用的一些数据结构和函数,文件系统只需要提供VFS所要求的数据和实现所要求的函数就可以了,就像是在VFS上开发一个插件一样。
文件系统在系统中的位置
下面这张图展示了文件系统在系统中的位置
+---------------------------------------------------------------+
| +---------------------+ |
| | User Applications | |
| +---------------------+ |
| | ↓ User Space |
| | +---------------+ |
| | | GNU C Library | |
| | +---------------+ |
|...................|.........|.................................|
| ↓ ↓ |
| +-------------------------+ |
| | System Call Interface | |
| +-------------------------+ |
| ↓ |
| +-----------+ +-------------------------+ +---------------+ |
| |Inode Cache|--| Virtual File System |--|Directory Cache| |
| +-----------+ +-------------------------+ +---------------+ |
| ↓ |
| +-------------------------+ |
| | Individual File System | |
| +-------------------------+ |
| ↓ |
| +----------------+ |
| | Buffer Cache | Kernel Space |
| +----------------+ |
| ↓ |
| +----------------+ |
| | Device Driver | |
| +----------------+ |
+---------------------------------------------------------------+
应用层程序(User Applications)可以通过libc(GNU C Library),或者直接通过内核提供的系统调用(System Call Interface )来访问文件
在内核里面,相应的系统调用里面调用的其实就是VFS提供的函数
VFS根据文件路径找到相应的挂载点,就得到了具体的文件系统信息,然后调用具体文件系统的相应函数。(Inode Cache和Directory Cache是VFS中的一部分,用来加快inode和directory的访问)
具体的文件系统根据自己对磁盘(可能是别的介质,本篇统一以磁盘为例)上数据的组织方式,操作相应的数据。(Buffer Cache是内核中块设备的缓存)
VFS相关的对象
下面这张图简要的说明了VFS里面各种object之间的关系
. . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. Process A . . . . .
. fd . . Kernel . . File System .
. +---+ . . +--------------+ . . .
. stdin | 0 |-------------->| File Object1 |--------+ . . .
. +---+ . . +--------------+ | . . .
. stdout | 1 |-------+ . +--------------+ | . . .
. +---+ . +------>| File Object2 |------+ | . . .
. stderr | 2 |-------+ . +--------------+ | | . . +------------+ .
. +---+ . . +--------------+ | | . +------->|Inode Object|--+ +-----------------+ .
. | 3 |-------------->| File Object3 |----+ | | DEntry Cache . | . +------------+ | +->|Superblock Object| .
. +---+ . . +--------------+ | | | +-------------+ . | . +------------+ | | +-----------------+ .
. |...| . . +--+-+-+->|DEntry Object|------+ +---->|Inode Object|--+ | | .
. +---+ . . | | | +-------------+ . | . +------------+ +--+ | .
. . . . . .. . . . . . | | +--->|DEntry Object|---------+ . +------------+ | | ↓ .. | | +-------------+ . .+->|Inode Object|--+ | +-----------------+ .. | +----->|DEntry Object|------------+ +------------+ | | | | .
. . . . . .. . . . . . | | +-------------+ . . +------------+ | +->| Disk | .
. Process B . . | | +-->|DEntry Object|-------------->|Inode Object|--+ | | .
. fd . . +--------------+ | | | +-------------+ . . +------------+ +-----------------+ .
. +---+ . +------>| File Object4 |-+ | | | ..... | . . .
. stdin | 0 |-------+ . +--------------+ | | +-------------+ . . .
. +---+ . . +--------------+ | | . . .
. stdout | 1 |-------------->| File Object5 |----+ | . . .
. +---+ . . +--------------+ | | . . .
. stderr | 2 |-------+ . +--------------+ | | . . .
. +---+ . +------>| File Object6 |----+ | . . .
. | 3 |---+ . . +--------------+ | . . .
. +---+ | . . +--------------+ | . . .
. |...| +---------->| File Object7 |-------+ . . .
. +---+ . . +--------------+ . . .
. . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
fd列表
在进程的眼里,看到的是fd列表,列表里面存放的是指向file object的指针,所以同样的fd在不同的进程中可能会指向不同的file object
File Object
file object是内核中的对象,代表了一个被进程打开的文件,和具体的进程相关联
这里是它的数据结构(只摘取部分)
//linux/fs.h
struct file {mode_t f_mode; /*rwx权限及文件类型,来自inode object*/struct path f_path; /*文件的路径,由dentry object组成*/struct inode *f_inode; /*指向的inode*/const struct file_operations *f_op; /*和文件相关的函数,比如read,write等,来自inode object*/loff_t f_pos; /*当前文件访问到的位置*/
}//linux/path.h
struct path {struct vfsmount *mnt; /*所属的挂载点信息*/struct dentry *dentry; /*指向的dentry object*/
};
当应用程序调用open函数的时候,VFS就会创建相应的file object,除了f_pos是进程私有的数据外,其他的数据都来自于inode和dentry,和所有进程共享,不同进程的file object可以指向同一个dentry和inode
DEntry Objectry
DEntry Object由VFS维护,所有文件系统共享,不和具体的进程关联,每个DEntry Object都指向一个Inode object,在加载inode时根据inode自动生成。
当调用open函数打开一个文件时,内核会第一时间到dentry cache里面根据path来找相应的dentry,找到了就直接构造file object并返回,如果没找到的话,就会根据找到的最近的目录一级一级的往下加载,直到找到相应的文件。(加载的过程就是从磁盘加载inode的过程,所有被加载的inode都会生成相应的dentry然后缓存起来)
dentry chache的作用就是用来加快根据path找到相应文件的速度,它里面有自己设计的便于快速查找的数据结构,dentry只存在于内存中,不会被存储在磁盘上,由于内存有限,所以并不是磁盘上所有inode所对应的dentry都会被缓存起来,VFS有自己的缓存策略。
这里是它的数据结构(只摘取部分)
//linux/dcache.h
struct dentry {struct dentry *d_parent; /* 父目录 */struct qstr d_name; /* 名字 */struct inode *d_inode; /* 关联的inode */ */struct list_head d_child; /* 父目录中的子目录和文件 */struct list_head d_subdirs; /* 当前目录中的子目录和文件 */
};
注意:dentry虽然名字叫directory entry,实际上它对应的inode也可以是普通文件
Inode object
inode的结构体由VFS定义,代表了磁盘上的一个文件、目录、链接或者其它类型的文件。
inode里面包含的数据存放在磁盘上,由具体的文件系统进行组织,当需要访问一个inode时,会由文件系统从磁盘上加载相应的数据并构造好相应的inode
一个inode可能被多个dentry所关联,比如多个hard links指向同一个文件的情况
这里是它的数据结构(只摘取部分)
//linux/fs.h
struct inode {umode_t i_mode; /*rwx权限及文件类型*/kuid_t i_uid; /*user id*/kgid_t i_gid; /*group id*/const struct inode_operations *i_op; /*inode相关的操作函数,如创create,mkdir,lookup,rename等,请参考fs.h里的定义*/struct super_block *i_sb;unsigned long i_ino; /*inode的编号*/loff_t i_size; /*文件大小*/struct timespec i_atime; /*最后访问时间*/struct timespec i_mtime; /*文件内容最后修改时间*/struct timespec i_ctime; /*文件元数据最后修改时间(包括文件名称)*/const struct file_operations *i_fop; /* 文件操作函数,包括open,llseek,read,write等,请参考fs.h里的定义 */void *i_private; /* 文件系统的私有数据,一般可以从这里面知道文件对应的数据在哪 */
};
Superblock Object
它的结构体由VFS定义,但里面的数据由具体的文件系统填充,每个superblock代表了一个具体的分区。
每个磁盘分区上都有一份superblock,里面包含了当前磁盘分区的信息,如文件系统类型、剩余空间等。
由于superblock非常重要,所以一般文件系统都会在磁盘上存储多份,防止数据损坏导致整个分区无法读取。
这里是它的数据结构(只摘取部分)
//linux/fs.h
struct super_block {unsigned long s_blocksize; /* block的大小,常见文件系统一般都是4K */loff_t s_maxbytes; /* 支持的最大文件大小 */struct file_system_type *s_type; /* 文件系统系统类型 */struct dentry *s_root; /* 分区内文件树的根节点 */struct list_head s_mounts; /* 一个分区可以mount到多个地方,这里是mount的相关信息*/struct block_device *s_bdev; /* 对应的物理设备信息 */u8 s_uuid[16]; /* 分区的UUID */void *s_fs_info; /* 文件系统的私有数据*/
};
实现文件系统的大概步骤
文件系统主要负责管理磁盘上的空间,磁盘上至少要包含三部分数据: superblock,inodes和数据块。
首先得有一个创建文件系统的工具(如ext2文件系统的mke2fs),用来将磁盘分区格式化成想要的格式,主要是初始化superblock和root inode。
写一个内核模块,在里面注册自己的文件系统,并且初始化mount函数
当用户在应用层调用mount命令时,VFS就会根据指定的文件系统类型找到我们写的内核模块,并且调用里面的mount函数
在mount函数里面读取磁盘上的superblock和root inode
初始化root inode的inode_operations和file_operations,然后返回给VFS
这样VFS就能根据root inode里提供的函数一级一级的往下找到path对应文件的inode
读取inode所指向的数据块(一个或者多个),根据文件的类型,解析数据块的内容。如果文件类型是普通文件,那么数据块里面就是文件的内容;如果文件类型是目录,那么数据块里面存储的就是目录下面所有子目录和文件的名称及它们对应的inode号;如果文件类型是软链接,那么数据块里面存储的就是链接到的文件路径。
总的来说,实现文件系统就是怎么在磁盘上组织文件,然后实现VFS所要求的superblock,inode以及inode_operations和file_operations。
结束语
本篇只是介绍了VFS里面的基本概念,没有深入细节(因为我也没有相关经验),希望对大家理解文件系统有所帮助。
要实现一个真正的文件系统除了需要了解VFS外,还需要很多内核编程及磁盘操作的知识,如果感兴趣,可以参考ext2文件系统的实现,相对简单且代码少(不到1万行)。
参考
Linux 文件系统剖析
Overview of the Linux Virtual File System
Creating Linux virtual filesystems
Linux虚拟文件系统简介相关推荐
- linux虚拟文件系统浅析
linux虚拟文件系统浅析 虚拟文件系统(VFS) 在我看来, "虚拟"二字主要有两层含义: 1, 在同一个目录结构中, 可以挂载着若干种不同的文件系统. VFS隐藏了它们的实现细 ...
- linux 文件系统 vfs,linux虚拟文件系统vfs
<操作系统>课程设计报告课程设计题目:操作系统课程设计 设计时间:2016/1/10一. 课程设计目的与要求需要完成的内容:(1) 安装虚拟机:Vmware.Vmware palyer ( ...
- Linux虚拟文件系统:数据结构与文件系统注册、文件打开读写
数据结构 超级块 - super_block 索引节点 - inode 目录项 - dentry 文件结构 - file 虚拟文件系统实现 注册文件系统 - register_filesystem 打 ...
- Linux虚拟文件系统
从文件 I/O 看 Linux 的虚拟文件系统 1 引言 Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等.通过使用同一套文件 I/O 系统 调用即可对 Linux ...
- linux 目录防篡改,一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法
一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法 [技术领域] [0001]本发明涉及文件防护技术领域,特别涉及一种基于Linux虚拟文件系统的防篡改方法及系统. [背景技术] [0002] ...
- Linux 虚拟文件系统(一)概述
Linux 虚拟文件系统(一)概述 tags: Linux源码 Linux 虚拟文件系统一概述 文章梗概 正文 文件系统 虚拟文件系统架构 虚拟文件系统如何知道可用的文件系统有哪些的 不太喜欢的环节 ...
- Linux 虚拟文件系统四大对象:超级块、inode、dentry、file之间关系
一:文件系统 1. 什么是文件系统? 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 通常文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 文件系统 ...
- linux VFS 虚拟文件系统 简介 super_block inode dentry file
1.简介 1.Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等.通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文 ...
- 自学 Linux 8—文件系统简介之 Linux 下的文件系统
在 UNIX 族的操作系统中,文件系统占有十分重要的地位,文件的概念涵盖了 UNIX 设备和操作对象的全部内容,对设备的操作方式几乎可以与对普通文件的操作等价.本博客对文件系统进行简单的介绍,主要 ...
最新文章
- win7更新powershell到5.1
- python读取csv某一列存入数组_python 读取.csv文件数据到数组(矩阵)的实例讲解
- Hadoop HBase概念学习系列之HBase的Shell(步骤非常清晰)(二十四)
- checkbox居中 editor_如何在ListBoxItem中居中WPF CheckBox
- 两台centos之间免密传输 scp
- WordPress 不用插件实现对长文章进行分页
- 区块链爆史诗级漏洞,可完全控制虚拟货币交易!
- python游戏开发引擎_【图片】有关Ren'Py引擎的游戏制作汉化教程【linux游戏吧】_百度贴吧...
- 基于协同过滤算法的旅游推荐系统
- 浅述狭义相对论的钟慢效应和尺缩效应
- 电子计算机属于输出设备的是,下列设备属于输入设备 下列设备中属于输出设备的是 A.键盘 B.鼠标 C.显示器 D.扫描仪...
- php如何计算天数,php计算日期相差天数二种方法
- 英雄联盟 LPL比赛 直播 视频地址 使用VLC播放
- photoshop教程:替换颜色
- 单片机理论篇(未完成)
- 国际音标(IPA)和美国音标(KK)对照表
- subprocess
- ArrayList删除元素的细则
- 椭圆一般方程求解椭圆标准方程参数
- 不入小程序,则为大笨熊