1.简介

1.Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等。通过使用同一套文件 I/O 系统 调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式;更进一步,对文件的 操作可以跨文件系统而执行。

2.而虚拟文件系统正是实现上述两点 Linux 特性的关键所在。虚拟文件系统(Virtual File System, 简称 VFS), 是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的文件系统共存。

3.系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。为了能够支持各种实际文件系统,VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据 结构;同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构,将自身的诸如文件、目录等概念在形式 上与VFS的定义保持一致。

4.换句话说,一个实际的文件系统想要被 Linux 支持,就必须提供一个符合VFS标准 的接口,才能与 VFS 协同工作。实际文件系统在统一的接口和数据结构下隐藏了具体的实现细节,所以在VFS 层和内核的其他部分看来,所有文件系统都是相同的。

VFS和具体文件系统 如图:

2.虚拟文件系统(VFS)

为了支持不同的文件系统,必须将不同的文件系统的操作和管理纳入一个统一框架,使用户程序可以通过一个文件系统界面,(同一组系统调用)能够对不同文件系统和文件进行操作。从本质上讲,文件系统是特殊的数据分层存储结构,它包含文件、目录和相关的控制信息。为了描述 这个结构,Linux引入了一些基本概念:

文件 一组在逻辑上具有完整意义的信息项的系列。在Linux中,除了普通文件,其他诸如目录、设备、套接字等 也以文件被对待。总之,“一切皆文件”。

目录 目录好比一个文件夹,用来容纳相关文件。因为目录可以包含子目录,所以目录是可以层层嵌套,形成 文件路径。在Linux中,目录也是以一种特殊文件被对待的,所以用于文件的操作同样也可以用在目录上。

目录项 在一个文件路径中,路径中的每一部分都被称为目录项;如路径/home/source/helloworld.c中,目录 /, home, source和文件 helloworld.c都是一个目录项。

索引节点 用于存储文件的元数据的一个数据结构。文件的元数据,也就是文件的相关信息,和文件本身是两个不同 的概念。它包含的是诸如文件的大小、拥有者、创建时间、磁盘位置等和文件相关的信息。

超级块 用于存储文件系统的控制信息的数据结构。描述文件系统的状态、文件系统类型、大小、区块数、索引节 点数等,存放于磁盘的特定扇区中。

磁盘与文件系统如图:

3.VFS数据结构

VFS依靠四个主要的数据结构和一些辅助的数据结构来描述其结构信息,这些数据结构表现得就像是对象; 每个主要对象中都包含由操作函数表构成的操作对象,这些操作对象描述了内核针对这几个主要的对象可以进行的操作。

  • 超级块对象

存放系统中已安装文件系统的信息

  • 索引节点对象

存放关于具体文件的一般信息

  • 目录项对象

存放目录项与对应文件进行链接的信息

  • 文件对象

存放打开文件与进程之间进行交互的有关信息

4.超级块对象

存储一个已安装的文件系统的控制信息,代表一个已安装的文件系统;每次一个实际的文件系统被安装时, 内核会从磁盘的特定位置读取一些控制信息来填充内存中的超级块对象。一个安装实例和一个超级块对象一一对应。 超级块通过其结构中的一个域s_type记录它所属的文件系统类型。

struct super_block
{struct list_head               s_list; /* Keep this first 指向超级块链表的指针*/dev_t                            s_dev; /* search index; _not_ kdev_t 具体文件系统的块设备描述符*/unsigned char                   s_blocksize_bits;unsigned long                  s_blocksize; /*以字节为单位的数据块的大小*/loff_t                            s_maxbytes; /* Max file size */struct file_system_type *        s_type; /*文件系统类型*/const struct super_operations * s_op;   /*指向超级块操作的函数集合*/const struct dquot_operations * dq_op;const struct quotactl_ops *     s_qcop;const struct export_operations *s_export_op;unsigned long                    s_flags;unsigned long                   s_iflags; /* internal SB_I_* flags */unsigned long                  s_magic;struct dentry *                 s_root;struct rw_semaphore              s_umount;int                                s_count;atomic_t                        s_active;
#ifdef CONFIG_SECURITYvoid *s_security;
#endifconst struct xattr_handler **s_xattr;struct hlist_bl_head  s_anon;       /* anonymous dentries for (nfs) exporting */struct list_head      s_mounts; /* list of mounts; _not_ for fs use */struct block_device *   s_bdev;struct backing_dev_info *s_bdi;struct mtd_info *         s_mtd;struct hlist_node         s_instances;unsigned int            s_quota_types; /* Bitmask of supported quota types */struct quota_info      s_dquot; /* Diskquota specific options */struct sb_writers s_writers;char s_id[32];                /* Informational name */u8   s_uuid[16];              /* UUID */void *       s_fs_info;         /* Filesystem private info 具体文件系统的私有数据*/unsigned int s_max_links;fmode_t         s_mode;/* Granularity of c/m/atime in ns.Cannot be worse than a second */u32 s_time_gran;/** The next field is for VFS *only*. No filesystems have any business* even looking at it. You had been warned.*/struct mutex s_vfs_rename_mutex;    /* Kludge *//** Filesystem subtype.  If non-empty the filesystem type field* in /proc/mounts will be "type.subtype"*/char *s_subtype;/** Saved mount options for lazy filesystems using* generic_show_options()*/char __rcu *                 s_options;const struct dentry_operations *s_d_op; /* default d_op for dentries *//** Saved pool identifier for cleancache (-1 means none)*/int cleancache_poolid;struct shrinker s_shrink;    /* per-sb shrinker handle *//* Number of inodes with nlink == 0 but still referenced */atomic_long_t s_remove_count;/* Being remounted read-only */int s_readonly_remount;/* AIO completions deferred from interrupt context */struct workqueue_struct *s_dio_done_wq;struct hlist_head      s_pins;/** Keep the lru lists last in the structure so they always sit on their* own individual cachelines.*/struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;struct list_lru s_inode_lru  ____cacheline_aligned_in_smp;struct rcu_head                rcu;struct work_struct          destroy_work;struct mutex s_sync_lock;           /* sync serialisation lock *//** Indicates how deep in a filesystem stack this SB is*/int s_stack_depth;/* s_inode_list_lock protects s_inodes */spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;struct list_head            s_inodes; /* all inodes 所有的inodes*/
};
  • 超级块用来描述整个文件系统的信息
  • 每个具体的文件系统都有自己的超级块
  • VFS超级块是各种文件系统在安装时建立的,并在卸载时被自动删除,其数据结构是super_block
  • 所有超级块对象都以双向循环链表的形式链接在一起

5.索引节点对象

struct inode
{umode_t           i_mode;unsigned short i_opflags;kuid_t          i_uid;kgid_t        i_gid;unsigned int   i_flags;#ifdef CONFIG_FS_POSIX_ACLstruct posix_acl *i_acl;struct posix_acl *i_default_acl;
#endifconst struct inode_operations *i_op;struct super_block *         i_sb;struct address_space *         i_mapping;#ifdef CONFIG_SECURITYvoid *i_security;
#endif/* Stat data, not accessed from path walking */unsigned long i_ino;/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union{const unsigned int i_nlink;unsigned int      __i_nlink;};dev_t            i_rdev;loff_t           i_size;struct timespec i_atime;struct timespec i_mtime;struct timespec i_ctime;spinlock_t       i_lock;      /* i_blocks, i_bytes, maybe i_size */unsigned short    i_bytes;unsigned int    i_blkbits;blkcnt_t      i_blocks;#ifdef __NEED_I_SIZE_ORDEREDseqcount_t i_size_seqcount;
#endif/* Misc */unsigned long i_state;        /*索引节点的状态标志*/struct mutex  i_mutex;unsigned long dirtied_when;           /* jiffies of first dirtying */unsigned long dirtied_time_when;struct hlist_node i_hash;    /*指向哈希链表的指针*/struct list_head  i_io_list;      /* backing dev IO list */
#ifdef CONFIG_CGROUP_WRITEBACKstruct bdi_writeback *i_wb;           /* the associated cgroup wb *//* foreign inode detection, see wbc_detach_inode() */int i_wb_frn_winner;u16 i_wb_frn_avg_time;u16 i_wb_frn_history;
#endifstruct list_head i_lru;           /* inode LRU list 指向索引节点链表的指针*/struct list_head i_sb_list;    /*指向超级块的指针*/union{struct hlist_head i_dentry;struct rcu_head    i_rcu;};u64        i_version;atomic_t i_count;atomic_t i_dio_count;atomic_t i_writecount;
#ifdef CONFIG_IMAatomic_t i_readcount;        /* struct files open RO */
#endifconst struct file_operations *i_fop;       /* former ->i_op->default_file_ops */struct file_lock_context *    i_flctx;struct address_space        i_data;struct list_head             i_devices;union{struct pipe_inode_info *i_pipe;struct block_device *  i_bdev;struct cdev *            i_cdev;char *                   i_link;};__u32 i_generation;#ifdef CONFIG_FSNOTIFY__u32           i_fsnotify_mask; /* all events this inode cares about */struct hlist_head i_fsnotify_marks;
#endifvoid *i_private;            /* fs or device private pointer */
};
  • 文件系统处理文件所需要的所有信息都保存在称为索引节点的inode结构体中
  • 同一个文件系统中,每个文件的索引节点号都是唯一的
  • 与索引节点关联的方法由struct inode_operations来描述
  • inode有两个设备号:i_dev(常规文件的设备号),i_rdev(某一设备的设备号)
  • LInux文件系统的另外一大特色:设备即文件。驱动中设备号的来源

6.目录项对象

struct dentry {/* RCU lookup touched fields */unsigned int d_flags;        /* protected by d_lock */seqcount_t d_seq;        /* per dentry seqlock */struct hlist_bl_node d_hash;    /* lookup hash list */struct dentry *d_parent;    /* parent directory */struct qstr d_name;struct inode *d_inode;        /* Where the name belongs to - NULL is* negative */unsigned char d_iname[DNAME_INLINE_LEN];    /* small names *//* Ref lookup also touches following */struct lockref d_lockref;    /* per-dentry lock and refcount */const struct dentry_operations *d_op;struct super_block *d_sb;    /* The root of the dentry tree */unsigned long d_time;        /* used by d_revalidate */void *d_fsdata;            /* fs-specific data */union {struct list_head d_lru;        /* LRU list */wait_queue_head_t *d_wait;    /* in-lookup ones only */};struct list_head d_child;    /* child of parent list */struct list_head d_subdirs;    /* our children *//** d_alias and d_rcu can share memory*/union {struct hlist_node d_alias;    /* inode alias list */struct hlist_bl_node d_in_lookup_hash;    /* only for in-lookup ones */struct rcu_head d_rcu;} d_u;};
  • 每个文件除了一个struct inode结构体外,还要一个目录项struct dentry结构
  • dentry代表的逻辑意义上的文件,描述的是文件逻辑上的属性,目录项对象在磁盘上并没有对应的映像
  • inode代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统,其inode在磁盘上有对应的映像
  • 一个索引节点可能对应多个目录项对象

7.文件对象

struct file
{union{struct llist_node fu_llist;      //文件对象链表struct rcu_head   fu_rcuhead;      //释放之后的RCU链表}                              f_u;struct path                     f_path;struct inode *               f_inode; /* cached value */const struct file_operations *f_op;/** Protects f_ep_links, f_flags.* Must not be taken from IRQ context.*/spinlock_t           f_lock;atomic_long_t        f_count;      //文件对象的使用计数unsigned int       f_flags;     //当打开文件时所使用的标志fmode_t              f_mode;      //文件的访问模式struct mutex      f_pos_lock;loff_t               f_pos;       //文件当前的位移量struct fown_struct   f_owner;      //拥有者通过信号量进行异步I/O传输const struct cred *    f_cred;struct file_ra_state f_ra;u64 f_version;
#ifdef CONFIG_SECURITYvoid *f_security;                //安全模块
#endif/* needed for tty driver, and maybe others */void *private_data;                //tty 设备驱动的钩子#ifdef CONFIG_EPOLL/* Used by fs/eventpoll.c to link all the hooks to this file */struct list_head f_ep_links;        //事件池锁struct list_head f_tfile_llink;
#endif    /* #ifdef CONFIG_EPOLL */struct address_space *f_mapping;        //页缓存映射
} __attribute__((aligned(4)));       /* lest something weird decides that 2 is OK */
  • 进程通过文件描述符来访问文件
  • LInux用一个file文件对象来保存打开文件的位置,这个对象称为打开的文件描述符
  • file结构主要保存了文件位置,还把指向文件索引节点的指针也放在其中
  • file结构形成一个双链表,称为系统打开文件表

对象间的联系以上的数据结构并不是孤立存在的。正是通过它们的有机联系,VFS才能正常工作。下图是对它们之间的联系的描述。

  • 超级块是对一个文件系统的描述
  • 索引节点是对一个文件物理属性的描述
  • 目录项是对一个文件逻辑属性的描述
  • 一个进程所处的位置由fs_struct描述
  • 一个进程(或用户)打开的文件由files_struct描述
  • 整个系统所打开的文件由 file结构来描述

linux VFS 虚拟文件系统 简介 super_block inode dentry file相关推荐

  1. 【操作系统】LinuxKernel-VFS虚拟文件系统 认知框架构建(super_block,inode,dentry,file)

    VFS 概念 虚拟文件系统(也称为虚拟文件系统交换机)是内核中的软件层,为用户空间程序提供文件系统接口.它还在内核中提供了一个抽象,允许不同的文件系统实现共存 "一切皆文件"是Li ...

  2. Linux·VFS虚拟文件系统

    目录 1 概念 2 架构 3 接口适配示例 4 跨设备/文件系统示例 5 VFS的抽象接口 6 Linux系统VFS支持的文件系统 7 统一文件模型(common file model) 7.1 Su ...

  3. Linux 字符设备驱动开发基础(六)—— VFS 虚拟文件系统解析

    一.VFS 虚拟文件系统基础概念 Linux 允许众多不同的文件系统共存,并支持跨文件系统的文件操作,这是因为有虚拟文件系统的存在.虚拟文件系统,即VFS(Virtual File System)是 ...

  4. Linux(一) VFS虚拟文件系统

    一.先了解一下什么是挂载 Linux有自己的一套文件系统,例如Ext2.Ext3,但是外部其他文件系统时,由于各个文件系统都各自有一套的文件管理体系,是无法通过Linux本身访问文件的方式直接访问的, ...

  5. 【Linux】Linux的虚拟文件系统

    Linux的虚拟文件系统与实际文件系统的关系如下所示: VFS的原理 各种文件系统之所以有区别,就在于它们的目录文件结构各不相同,随之而来的也就是对文件目录的操作函数也不相同.对于前者可以在保留原系统 ...

  6. VFS - 虚拟文件系统基本操作方法的封装

    VFS - 代码生成器预览功能实现 VFS - 虚拟文件系统基本操作方法的封装 VFS - 虚拟文件系统的加载和导出 接前一篇 VFS - 代码生成器预览功能实现 ,上一篇讲到了 mkdirs 封装创 ...

  7. VFS - 虚拟文件系统的加载和导出

    VFS - 代码生成器预览功能实现 VFS - 虚拟文件系统基本操作方法的封装 VFS - 虚拟文件系统的加载和导出 这是 VFS 的最后一篇,前面两篇中的基本方法已经实现了一个简单的虚拟文件系统,可 ...

  8. Linux虚拟文件系统简介

    本文将对Linux下的VFS做一个简单介绍,主要包括VFS里面的一些概念,以及文件系统是如何与VFS交互的. 本文所涉及的代码摘自Linux-4.4.0-59 什么是VFS VFS的全称为virtua ...

  9. linux文件系统与模型【笔记】 surper block/inode/dentry/file

    因为有文件,所以有管理文件的系统=>因为有很多种文件系统,所以有虚拟文件系统对它们进行封装,让上层的程序只需要调用简单的接口. 文件系统是存储和组织信息的机制,它的目的是管理各种存储设备,所谓的 ...

最新文章

  1. Android -- TextView与EditText 同步显示
  2. 踏青赏花正当时-北京大觉寺游记图
  3. 串—KMP算法(详细)
  4. Revit二次开发之“使用ElementTransformUtils.MoveElement()移动元素”
  5. android camera(三):camera V4L2 FIMC
  6. Understand one Simple Factory Pattern
  7. python格式化字符串_Python笔记7:三种方式构建字符串-格式化
  8. Tensorflow快餐教程(9) - 卷积
  9. 创造黑科技,守护新未来 | 360公司2019年春季校园招聘正式启动!
  10. php 连接sap rfc 乱码,[RFC] sap rfc调用时判断连接状态
  11. 告白气球--吉他教学
  12. 安装之后如何激活冰点还原软件?
  13. 个人简历自我介绍求职面试PPT模板
  14. 利用模式进行构建第十一讲——文档版本控制模式
  15. 唱响艾泽拉斯_战争篇
  16. 物联网开发笔记(5)- 使用Wokwi仿真树莓派Pico实现LED灯交替闪烁(续)
  17. R语言 - RStudio使用Git版本控制
  18. linux常用命令大全(linux基础命令入门到精通+实例讲解+持续更新+命令备忘录+面试复习)
  19. 如何在cmd命令行下切换目录
  20. 什么是星际文件系统(IPFS)

热门文章

  1. Devstack 配置文件说明手册
  2. Keil仿真出现Can not read register xx while CPU is running
  3. 深度学习CTR预估模型凭什么成为互联网增长的关键?
  4. Java学习笔记二十:Java中的内部类
  5. vscode新建html,没有模板
  6. 网站的高性能架构---存储性能优化
  7. 什么是GREENPLUM
  8. select 忽略查询字段值大小写【小技巧】
  9. 关于mysql的调优
  10. 颜色缩减(带Trackbar)【从毛星云Opencv3编程入门P75 P111例程改编】