首页 > 运维 > linux运维 > 正文

通俗易懂!快速了解虚拟文件系统(VFS)

看不見的法師
发布: 2025-07-14 09:47:04
原创
539人浏览过

前言

为什么 Linux 内核支持如此多种类的文件系统,并且都能顺利挂载呢?为什么可以在系统中直接挂载其他文件系统,甚至将 Windows 下的文件夹挂载到 Linux 上?Linux 的虚拟文件系统(VFS)为何如此强大?这都归功于其精妙的数据结构设计。似乎有个说法,Linux 有什么解决不了的问题?就加一层。

通俗易懂!快速了解虚拟文件系统(VFS)

VFS 是什么?虚拟文件系统,简称 VFS(Virtual Filesystem),是内核中的一个软件层。

VFS 的作用可以概括为两点:

  1. 处理与 Unix 标准文件系统相关的所有系统调用。
  2. 为各种文件系统提供一个通用的接口。

VFS 支持的文件系统类型如下列出一些常见的文件系统类型,本文暂不进行详细分析。

  • 磁盘文件系统:ext2,ext3,...
  • 网络文件系统类型:nfs,smbfs,...
  • 特殊文件系统:tmpfs,ramfs,...
  • 伪文件系统:procfs,sysfs,...

VFS 的设计思想 VFS 设计的初衷是支持所有的文件系统,因此其设计思想是采用面向对象的方式,设计一个通用的文件模型。尽管出于效率考虑,VFS 是用 C 语言编写的。在通用文件系统模型中,每个目录也被视为一个文件,可以包含若干文件和其他子目录。因此,Linux 有一句经典的话:一切皆文件。

关键数据结构介绍 Linux VFS 抽象出四种类型的数据结构,以实现将不同类型的文件系统挂载到目录结构中。

百度虚拟主播
百度虚拟主播

百度智能云平台的一站式、灵活化的虚拟主播直播解决方案

百度虚拟主播 36
查看详情 百度虚拟主播

超级块对象 对于磁盘类文件系统,超级块是存放在磁盘上的文件系统控制块,里面存放已安装文件系统的相关信息。换句话说,一个超级块描述了一个具体文件系统的信息,其中的信息非常重要,也称为元数据。与普通的文件数据相比,元数据的丢失会损坏整个文件系统,导致无法挂载等问题。当然,不仅超级块,inode 上也有许多元数据。

struct super_block {
  struct list_head s_list; // 超级块链表指针
  dev_t s_dev;  // 设备标识符
  unsigned char s_blocksize_bits; // 以位为单位的块的大小
  unsigned long s_blocksize; // 以字节为单位的块大小
  loff_t s_maxbytes; // 文件大小的上限
  struct file_system_type *s_type;  // 指向文件系统的 file_system_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_magic; // 文件系统的魔术字
  struct dentry *s_root;  // 目录登录点
  struct rw_semaphore s_umount; // 卸载信号量
  int s_count; // 超级块引用计数
  atomic_t s_active; // 活动引用记数
  #ifdef CONFIG_SECURITY
  void *s_security; // 安全模块
  #endif
  const struct xattr_handler **s_xattr;
  struct list_head s_inodes; // 把所有索引对象链接在一起,存放的是头结点
  struct hlist_bl_head s_anon; // 匿名目录项
  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; // 限额相关选项
  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;
  u32 s_time_gran;
  struct mutex s_vfs_rename_mutex; /* Kludge */
  char *s_subtype;
  char __rcu *s_options;
  const struct dentry_operations *s_d_op; /* default d_op for dentries */
  int cleancache_poolid;
  struct shrinker s_shrink; /* per-sb shrinker handle */
  atomic_long_t s_remove_count;
  int s_readonly_remount;
  struct workqueue_struct *s_dio_done_wq;
  struct hlist_head s_pins;
  struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;
  struct list_lru s_inode_lru ____cacheline_aligned_in_smp;
  struct rcu_head rcu;
  int s_stack_depth;
};
登录后复制

索引节点对象(inode) 索引节点存放关于具体文件的一般信息。对于磁盘类文件系统,索引节点也是存放在磁盘上的文件控制块。每个索引节点都有一个索引节点号,这个节点号唯一地标识了文件系统中的文件。

struct inode {
  umode_t i_mode; // 访问权限控制
  unsigned short i_opflags;
  kuid_t i_uid; // 使用者的 id
  kgid_t i_gid; // 使用组 id
  unsigned int i_flags; // 文件系统标志
  #ifdef CONFIG_FS_POSIX_ACL
  struct posix_acl *i_acl;
  struct posix_acl *i_default_acl;
  #endif
  const struct inode_operations *i_op; // 指向索引结点操作结构体的指针
  struct super_block *i_sb; // 指向 inode 所属文件系统的超级块的指针
  struct address_space *i_mapping; // 相关的地址映射
  #ifdef CONFIG_SECURITY
  void *i_security; // 安全模块
  #endif
  unsigned long i_ino; // 索引结点号。通过 ls -i 命令可以查看文件的索引节点号
  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_ORDERED
  seqcount_t i_size_seqcount;
  #endif
  unsigned long i_state; // 状态标志
  struct mutex i_mutex;
  unsigned long dirtied_when; // 首次修改时间
  unsigned long dirtied_time_when;
  struct hlist_node i_hash; // 散列表
  struct list_head i_wb_list; /* backing dev IO list */
  struct list_head i_lru; /* inode LRU list */
  struct list_head i_sb_list; // 链接一个文件系统中所有 inode 的链表
  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_IMA
  atomic_t i_readcount; /* struct files open RO */
  #endif
  const 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; // 字符设备
  };
  __u32 i_generation; // 索引节点版本号
  #ifdef CONFIG_FSNOTIFY
  __u32 i_fsnotify_mask; /* all events this inode cares about */
  struct hlist_head i_fsnotify_marks;
  #endif
  void *i_private; /* fs or device private pointer */
};
登录后复制

目录项对象(dentry) 存放 dentry 与对应文件链接的相关信息,每个 dentry 代表路径中的一个特定部分,每个磁盘类文件系统以自己的方式将目录项信息存放在磁盘上。

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 */
  struct list_head d_lru; /* LRU list */
  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 rcu_head d_rcu;
  } d_u;
};
登录后复制

文件对象(file) 存放被打开文件与进程间交互的信息,这类信息仅当进程访问文件期间存放在内存中。

struct file {
  union {
    struct llist_node fu_llist; // 每个文件系统中被打开的文件都会形成一个双链表
    struct rcu_head fu_rcuhead;
  } f_u;
  struct path f_path;
  struct inode *f_inode; /* cached value */
  const struct file_operations *f_op; // 指向文件操作表的指针
  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;
  const struct cred *f_cred;
  struct file_ra_state f_ra; // 预读状态
  u64 f_version; // 版本号
  #ifdef CONFIG_SECURITY
  void *f_security; // 安全模块
  #endif
  /* needed for tty driver, and maybe others */
  void *private_data;
  #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 */
struct file_handle {
  __u32 handle_bytes;
  int handle_type; /* file identifier */
  unsigned char f_handle[0];
};
登录后复制

数据结构组织关系图 通俗易懂!快速了解虚拟文件系统(VFS)

以上就是通俗易懂!快速了解虚拟文件系统(VFS)的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号