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

  • 1. 文件系统
    • 1.1 文件系统定义:
    • 1.2 文件系统分类
    • 1.3 标准文件系统:Ext文件系统族
    • 1.4 VFS
      • 1.4.1 VFS 背景
      • 1.4.2 VFS 定义
      • 1.4.3 VFS 意义
      • 1.4.4 VFS在Linux系统中的架构视图
  • 2. VFS 虚拟文件系统
    • 2.1 例子说明 VFS
      • 2.1.1 Linux VFS 支持的文件系统
      • 2.1.2 文件系统目录树(图)
      • 2.1.3 Ext2写数据流程例子
  • 3. VFS 统一文件模型(common file model)
    • 3.1 VFS如何对不同文件系统进行统一管理
    • 3.2 四种对象(超级快,目录项,索引节点,文件)
      • 3.2.1 四种对象1:super_block 超级块
      • 3.2.2 四种对象2:index node(inode)索引节点
        • 3.2.2.1 软/硬链接与inode关系
      • 3.2.3 四种对象3:dentry 目录项
      • 3.2.4 四种对象4:file 文件
      • 3.2.5 VFS file_system_type vfsmount 抽象组件间的关系
  • 4. 进程与文件系统关系(源码说明)

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

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

  1. Linux内核设计与实现笔记(一) 虚拟文件系统、块I/O层

    虚拟文件系统 系统内所有文件系统不但依赖VFS共存,而且也依靠VFS系统协同工作. VFS使得用户可以直接使用open/read/write等系统调用,而无需考虑具体文件系统和实际物理介质. VFS中 ...

  2. 跟我一起玩《linux内核设计的艺术》第1章(四)——from setup.s to head.s,这回一定让main滚出来!(已解封)

    看到书上1.3的大标题,以为马上就要见着main了,其实啊,还早着呢,光看setup.s和head.s的代码量就知道,跟bootsect.s没有可比性,真多--这确实需要包括我在内的大家多一些耐心,相 ...

  3. 跟我一起玩《linux内核设计的艺术》第1章(二)——linux内存加载和16位实模式使命的终结

    经过折腾了整整一篇的BIOS,总算可以跑linux 0.11内核源码了.第一个执行的是bootsect.s,如果现在你还没有下载linux 0.11的源码就赶紧去下载.如果自己懒得找,可以参见我下一篇 ...

  4. Linux 内核设计与实现之第17章 设备与模块

    1 设备类型    Linux中设备被分为三大类:块设备,字符设备,网络设备    块设备:寻址以块为单位,支持重定位操作(数据的随机访问).如硬盘,蓝光光碟等.块设备通过"块设备节点&qu ...

  5. linux简单设计与实现代码,《linux内核设计与实现》第五章(示例代码)

    第五章 系统调用 一.与内核通信 系统调用在用户空间进程和硬件设备之间添加了一个中间层.作用: 为用户空间提供了一种硬件的抽象接口. 系统调用保证了系统的稳定和安全. 每个进程都运行在虚拟系统中,而在 ...

  6. 《LINUX内核设计与实现》第五章学习总结

    一.与内核通信 系统调用:用户控件进程和硬件设备之间添加了一个中间层 系统调用的三个主要作用: 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进程都运行在虚拟系统中,而在用户 ...

  7. 读《Linux内核设计与实现》我想到了这些书

          从题目中可以看到,这篇文章是以我读<Linux内核设计与实现>而想到的其他我读过的书,所以,这篇文章的主要支撑点是<Linux内核>.       开始读这本书已经 ...

  8. 读 Linux内核设计与实现 我想到了这些书

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴!     ...

  9. Linux内核设计与实现学习笔记目录

    **注:**这是别人的笔记,我只是把目录抄过来 <Linux内核设计与实现学习笔记> 1.<Linux内核设计与实现>读书笔记(一)-内核简介 2.<Linux内核设计与 ...

最新文章

  1. 将图片的二进制字节 在HTML页面中显示
  2. Windows 窗体多线程
  3. BZOJ Usaco 1616 Cow Travelling
  4. SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy())
  5. 【AC Saber】二进制
  6. hdu 5124(线段树区间更新+lazy思想)
  7. android listview item点击时更改textview的颜色 代码中实现
  8. 怎样在Excel里第一格设计斜线表头
  9. LeetCode解题的常见模式套路
  10. Lock锁实现多线程卖票
  11. K8S精华问答 | 如何监控部署在Docker容器上的应用程序?
  12. python中模运算_Python中的模运算
  13. 【翻译】Adaptive Convolutions for Structure-Aware Style Transfer
  14. 基于android的个人收支财务管理,基于Android的个人财务管理系统的设计与实现.doc...
  15. 中医教你按摩手指,治疗百病
  16. 保镖(2019CSP-S模拟2C)(贪心,线段树)
  17. 工业设备产品建模3d展示三维模型展示
  18. SpringBoot的幕后推手,五年Java开发者小米、阿里面经
  19. cjk-ext-e 字体
  20. Druid基本概念及架构介绍

热门文章

  1. RNN实现股票预测(别当真)
  2. 2020年如何成为全栈工程师
  3. html 增加选项,添加标签——给定标签选项
  4. 产品DAU下降如何分析
  5. Babel(es6与se5 之间相互转换)
  6. 当出现Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this
  7. linux解决bash: nc: command not found 安装nc、telnet、yum
  8. 百度权重怎么查询?哪里可以查询百度权重?
  9. 假设检验中的P值 与显著性水平的联系
  10. getchar,putchar与gets,puts的区别