Linux内核设计与实现(13)第十三章:虚拟文件系统

1. 文件系统

1.1 文件系统定义:

操作系统中负责管理和存储文件信息的软件称为文件系统

1.2 文件系统分类

1. 磁盘文件系统:
	这类文件系统数目最多,最常见:Ext2/3/4,xfs brtfs zfs HFS等
	这类文件系统大部分都是基于块设备的文件系统,文件系统的数据和元数据都保存在块设备上;
	
2. 网络文件系统:NFS等

3. 特殊文件系统:/proc,/tmpfs等

1.3 标准文件系统:Ext文件系统族

Linux中标准的文件系统为Ext文件系统族
Linux对Ext文件系统族的支持是最好的,因为VFS抽象层的组织与Ext文件系统类似,这样在处理Ext文件系统时可以提高性能,因为在Ext和VFS之间转换几乎不会损失时间。

1.4 VFS

1.4.1 VFS 背景

Linux内核支持装载不同的文件系统类型,不同的文件系统有各自管理文件的方式。
开发者不能为他们使用的每种文件系统采用不同的文件存取方式,这与操作系统作为一种抽象机制背道而驰。
为支持各种文件系统,Linux内核在用户进程(或C标准库)和具体的文件系统之间引入了一个抽象层,该抽象层称之为“虚拟文件系统(VFS)”。

1.4.2 VFS 定义

虚拟文件系统(Virtual File System, 简称 VFS):为多种文件系统提供统一的操作接口

详细说:
1.是 Linux 内核中的一个软件层,在具体的文件系统之上抽象的一层,用于给用户空间的程序提供文件系统接口。同时,它也提供了内核中的一个抽象功能,允许不同的文件系统共存

2.VFS 统一了文件系统的实现框架,使得在linux上实现新文件系统的工作变得简单。目前linux内核中已经支持60多种文件系统,linux内核可以以统一的方式访问各种I/O设备

1.4.3 VFS 意义

虚拟文件系统(VFS)是linux内核和存储设备之间的抽象层,主要有以下好处。

1.向上,对应用层提供一个标准的文件操作接口。
	简化了应用程序的开发,应用程序通过统一的系统调用访问各种存储介质
	
2.对下,对文件系统提供一个标准的接口,以便其他操作系统的文件系统可以方便的移植到Linux上。
	简化了新文件系统加入内核的过程:新文件系统只要实现VFS的各个接口即可,不需要修改内核部分。
	
3. VFS内部则通过一系列高效的管理机制,比如inode cache, dentry cache 以及文件系统的预读等技术,
	使得底层文件系统不需沉溺到复杂的内核操作,即可获得高性能;

4.VFS把一些复杂的操作尽量抽象到VFS内部,使得底层文件系统实现更简单

1.4.4 VFS在Linux系统中的架构视图

vfs4

在这里插入图片描述

2. VFS 虚拟文件系统

2.1 例子说明 VFS

1.用户写入一个文件,使用POSIX标准的write接口,会被操作系统接管,转调sys_write这个系统调用
2.然后VFS层接受到这个调用,通过自身抽象的模型,转换为对给定文件系统、给定设备的操作
这一关键性的步骤是VFS的核心,需要有统一的模型,使得对任意支持的文件系统都能实现系统的功能

这就是VFS提供的统一的文件模型(common file model),底层具体的文件系统负责具体实现这种文件模型,负责完成POSIX API的功能,并最终实现对物理存储设备的操作

2.1.1 Linux VFS 支持的文件系统

磁盘文件系统:Ext2/3/4,xfs brtfs zfs HFS等
Network 文件系统:NFS等
特殊文件系统:/proc,/tmpfs等

2.1.2 文件系统目录树(图)

vsf6
在同一个目录结构中, 可以挂载着若干种不同的文件系统. VFS隐藏了它们的实现细节, 为使用者提供统一的接口;
在这里插入图片描述

2.1.3 Ext2写数据流程例子

Ext2写数据流程
vfs7
在这里插入图片描述

3. VFS 统一文件模型(common file model)

VFS为了提供对不同底层文件系统的统一接口,需要有一个高度的抽象和建模,这就是VFS的核心设计——统一文件模型。

换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准的接口,才能与 VFS 协同工作

3.1 VFS如何对不同文件系统进行统一管理

统一文件模型是一个标准,各种具体文件系统的实现必须以此模型定义的各种概念来实现。

由于不同类型的文件系统差异,超级块和inode的结构不尽相同。
而VFS的作用就是通过具体的设备驱动获得某个文件系统中的超级块和inode节点,然后将其中的信息填充到内核中的struct super_block和struct inode中,以此来试图对不同文件系统进行统一管理。

3.2 四种对象(超级快,目录项,索引节点,文件)

目前的Linux系统的VFS都是源于Unix家族,Unix家族的VFS的文件模型定义了四种对象,这四种对象构建起了统一文件模型。

1.superblock:存储文件系统基本的元数据。 相当于一个文件系统
如文件系统类型、大小、状态
2.index node(inode):保存一个文件相关的元数据。
包括文件的所有者(用户、组)、访问时间、文件类型等,但不包括这个文件的名称。文件和目录均有具体的inode对应
3.directory entry(dentry):保存了文件(目录)名称和具体的inode的对应关系
用来粘合二者,同时可以实现目录与其包含的文件之间的映射关系
4.file:一组逻辑上相关联的数据,被一个进程打开并关联使用

3.2.1 四种对象1:super_block 超级块

定义:

超级块相当于一个文件系统。
用于存储文件系统的控制信息的数据结构。

内容:

文件系统的状态、类型、大小、区块数、索引节 点数等,存放于磁盘的特定扇区中

每次一个实际的文件系统被安装时, 内核会从磁盘的特定位置读取一些控制信息来填充内存中的超级块对象

//include/linux/fs.h 
struct super_block { //超级块数据结构
	struct list_head s_list;                /*指向超级块链表的指针*/
	……
	struct file_system_type  *s_type;       /*文件系统类型*/
	struct super_operations  *s_op;         /*超级块方法*/
	……
	struct list_head         s_instances;   /*该类型文件系统*/
	struct list_head	s_inodes;			/* all inodes */
	……
};

struct super_operations { //超级块方法
	……
	//该函数在给定的超级块下创建并初始化一个新的索引节点对象
	struct inode *(*alloc_inode)(struct super_block *sb);
	……
	//该函数从磁盘上读取索引节点,并动态填充内存中对应的索引节点对象的剩余部分
	void (*read_inode) (struct inode *);
	……
};

注:内核源码获取:www.kernel.org 直接获取

3.2.2 四种对象2:index node(inode)索引节点

定义:

索引节点对象存储了文件的相关信息,代表了存储设备上的一个实际的物理文件。
(这里的文件不仅是指我们平时所认为的普通的文件,还包括目录,特殊设备文件等等)。	

组成:

内核中的每一个文件或者目录都有一个inode,inode由两个主要部分组成:
1. 描述文件状态的元数据,文件元数据包括文件大小,权限,类型,时间;
2. 文件数据描述,则用来定义文件数据在磁盘上的存放位置。

当一个文件首次被访问时,内核会在内存中组装相应的索引节点对象,以便向内核提供对一个文件进行操 作时所必需的全部信息;这些信息一部分存储在磁盘特定位置,另外一部分是在加载时动态填充的。

//include/linux/fs.h 
struct inode {//索引节点结构
	……
	struct inode_operations  *i_op;     /*索引节点操作表*/
	struct file_operations   *i_fop;  /*该索引节点对应文件的文件操作集*/
	struct super_block       *i_sb;     /*相关的超级块*/
	……
};

struct inode_operations { //索引节点方法
	……
	//该函数为dentry对象所对应的文件创建一个新的索引节点,主要是由open()系统调用来调用
	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);

	//在特定目录中寻找dentry对象所对应的索引节点
	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
	……
};
3.2.2.1 软/硬链接与inode关系

链接是unix特有的概念,又分为软链接和硬链接

软链接:

1.软链接,以路径的形式存在。类似于Windows操作系统中的快捷方式。
2.软链接可以 跨文件系统 ,硬链接不可以
3.软链接可以对一个不存在的文件名进行链接
4.软链接可以对目录进行链接

硬链接:

1.硬链接,以文件副本的形式存在。但不占用实际空间。
2.不允许给目录创建硬链接
3.硬链接只有在同一个文件系统中才能创建
4.硬链接是两个文件共享同一个inode,

并不是所有的文件系统都支持符号链接和硬链接,比如fat, yaffs等文件系统并不支持符号链接。

Linux ln 命令 + 软链接
https://blog.csdn.net/lqy971966/article/details/107615845

3.2.3 四种对象3:dentry 目录项

定义:

在一个文件路径中,路径中的每一部分都被称为目录项
如:路径/home/source/test.c中,目录 /, home, source和文件 test.c都对应一个目录项对象

作用:

为了方便目录查找和路径解析等操作,提高文件查找速度

// include/linux/dcache.h 
struct dentry {//目录项结构
	……
	struct inode *d_inode;           /*相关的索引节点*/
	struct dentry *d_parent;         /*父目录的目录项对象*/
	struct qstr d_name;              /*目录项的名字*/
	……
	struct list_head d_subdirs;      /*子目录*/
	……
	struct dentry_operations *d_op;  /*目录项操作表*/
	struct super_block *d_sb;        /*文件超级块*/
	……
};

struct dentry_operations {
	//判断目录项是否有效;
	int (*d_revalidate)(struct dentry *, struct nameidata *);
	//为目录项生成散列值;
	int (*d_hash) (struct dentry *, struct qstr *);
	……
};

目录项的目的就是提高文件查找,比较的效率,所以访问过的目录项都会缓存在slab中。

slab 中缓存的名称一般就是 dentry ,可以通过如下命令查看:
[root@localhost home]# sudo cat /proc/slabinfo | grep dentry
dentry             46704  46704    192   42    2 : tunables    0    0    0 : slabdata   1112   1112      0
[root@localhost home]# 

关于slab: Linux内存管理之slab 1:slab原理
https://blog.csdn.net/lqy971966/article/details/112980005

3.2.4 四种对象4:file 文件

定义:

文件对象代表由进程打开的文件,是已打开的文件在内存中的表示。

特点:

由open()系统调用创建,由close()系统调用撤销。
因为多个进程可以同时打开和操作一个文件,所以同一个文件也可能存在多个对应的文件对象。

内容:

一个文件对象包括的内容就是编程语言支持设置的各种文件打开的flag、mode,文件名称、当前的偏移等,
其中非常重要的一个字段就是 f_op,指向了当前文件所支持的操作集合。

//include/linux/fs.h 
struct file {
	struct dentry *f_dentry;
	struct vfsmount *f_vfsmnt;
	struct file_operations *f_op; //文件操作类型 struct file_operations  
	mode_t f_mode;
	loff_t f_pos;
	struct fown_struct f_owner;
	unsigned int f_uid, f_gid;
	unsigned long f_version;
	...
}

3.2.5 VFS file_system_type vfsmount 抽象组件间的关系

vfs3
在这里插入图片描述
在这里插入图片描述

4. 进程与文件系统关系(源码说明)

struct task_struct {
	……
	struct fs_struct *fs;		/* filesystem information */
	struct files_struct *files;	/* open file information */
	struct nsproxy *nsproxy;	/* namespaces */
	……
}

fs 成员指向进程当前工作目录的文件系统信息
files 成员指向了进程打开的文件的信息
sproxy 指向了进程所在的命名空间,其中包含了虚拟文件系统命名空间

struct files_struct {
	atomic_t count; /* 共享该表的进程数 */
	rwlock_t file_lock; /* 保护以下的所有域,以免在tsk->alloc_lock中的嵌套*/
	int max_fds; /*当前文件对象的最大数*/
	int max_fdset; /*当前文件描述符的最大数*/
	int next_fd; /*已分配的文件描述符加1*/
	struct file ** fd; /* 指向文件对象指针数组的指针 */
	fd_set *close_on_exec; /*指向执行exec( )时需要关闭的文件描述符*/
	fd_set *open_fds; /*指向打开文件描述符的指针*/
	fd_set close_on_exec_init;/* 执行exec( )时需要关闭的文件描述符的初 值集合*/
	fd_set open_fds_init; /*文件描述符的初值集合*/
	struct file * fd_array[32];/* 文件对象指针的初始化数组*/
};

在这里插入图片描述

参考:
注:内核源码通过 www.kernel.org 直接获取
文件结构体参数详解参考:
https://blog.csdn.net/hbcbgcx/article/details/88361530
其他:
https://blog.csdn.net/qq_41572503/article/details/102885598
https://www.linuxidc.com/Linux/2014-02/96174.htm

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值