深入linux内核架构--虚拟文件系统VFS

本文深入探讨Linux内核的虚拟文件系统(VFS),讲解了文件系统类型、通用文件系统、inode、dentry及其状态、dentry缓存、super_block、address_space、file等核心概念,并通过实例解析了文件操作流程。了解VFS如何抽象和适配各种文件系统,以支持Linux下的文件操作。
摘要由CSDN通过智能技术生成

【推荐阅读】

Linux内核源码分析--内核启动之zImage自解压过程

你应该知道的Linux内核基础及内核编译

深入理解LINUX内核堆栈

【零声教育】vico老师教你怎么学习Linux内核

值得学习的Linux内核锁(一)

在Linux中,“万物兼文件”,我们知道在linux下面有很多文件系统,如EXT/2/3/4,XFS等,为了很好的支持各种类型的文件系统,Linux抽象了一层虚拟文件系统层,用于更加灵活的适配各种具体的文件系统实现。其基本架构如下:

虚拟文件系统架构

可以看到所有的虚拟文件系统操作都必须在内核态执行,这是由于对于系统存储及外部设备的访问极其复杂,这部分的操作不能交给用户去操作,否则系统会非常不稳定。

文件系统类型

  1. 基于磁盘的文件系统
    在非易失介质存储存储文件的经典方法,也就是为我们所熟知的各类文件系统,注入EXT2/3/4, FAT等
  2. 虚拟文件系统
    在内核中生成,是一种使用用户应用程序与用户通信的方法,最为人所知的就是proc文件系统,其不需要与任何种类的硬件上存储信息,所有的信息都存储在内存中,伴随着进程而消亡
  3. 网络文件系统
    这种文件系统可以访问其他计算机上的数据,本机不会陷入内核态,所有的请求会发送到其他机器执行,因此网络文件系统一般会以FUSE的形式挂载。

通用文件系统

虚拟文件系统定义了一些了方法和抽象以及文件系统中对象(或文件)的统一视图,但是在不同的实现中,会截然不同,其提供的是一个通用的全集,其提供的许多操作在某些子系统中并不需要,比如proc系统中的write_page操作。
在处理文件时,内核空间和用户空间使用的对象是不同的,在用户空间一个文件有一个"文件描述符"标识,是一个整数,也就是我们经常说的FD,只在一个进程内部有效,两个不同进程之间可以使用同一个FD;而FD对应的内核空间的数据结构是struct file,其主要的成员为address_space,address_space是真正与底层设备交互数据结构,而另外一个管理文件元信息的数据结构是inode,其存储着文件的链接,访问时间,版本,对应的后端设备,所在的超级块等等元信息,但是不包括文件名,文件名存储在struct dentry中,这是由于文件名是用于索引及管理inode的,而dentry就是用于管理inode的,而dentry则通过super_block索引。
下面我们就来具体讨论一下具体的各个结构及他们的关系,并讨论一下在linux中打开一个文件到写入具体经历了哪些事情。

VFS结构

inode

inode用于管理文件的元数据信息,包括权限信息,访问信息,链接信息,存储设备信息等, 对应的操作主要包括链接、权限、,其数据结构如下:

/*
 * Keep mostly read-only and often accessed (especially for
 * the RCU path lookup and 'stat' data) fields at the beginning
 * of the 'struct inode'
 */
struct inode {
    ...
    const struct inode_operations   *i_op; // inode的操作,与具体的文件系统相关
    struct super_block  *i_sb; // 超级块
    struct address_space    *i_mapping; // 地址空间,真正的与设备交互模块
        ...
    /* Stat data, not accessed from path walking */
    unsigned long       i_ino; // inode 编号
    /*
     * 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 timespec64   i_atime; // 最后访问时间
    struct timespec64   i_mtime; // 最后修改时间
    struct timespec64   i_ctime; // 创建时间
    spinlock_t          i_lock; /* i_blocks, i_bytes, maybe i_size */
    unsigned short      i_bytes; // 文件大小字节数
    u8                  i_blkbits;       // 文件大小对应的块长度
    u8                  i_write_hint;
    blkcnt_t            i_blocks; // 文件长度 / 块长度
 
#ifdef __NEED_I_SIZE_ORDERED
    seqcount_t      i_size_seqcount;
#endif
 
    /* Misc */
    unsigned long       i_state;
    struct rw_semaphore i_rwsem;
 
    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_WRITEBACK
    struct 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;
#endif
    struct list_head    i_lru;      /* inode LRU list */
    struct list_head    i_sb_list;
    struct list_head    i_wb_list;  /* backing dev writeback list */
    union {
        struct hlist_head   i_dentry; // 一个inode可能被多个dentry使用(link)
        struct rcu_head i_rcu;
    };
    atomic64_t  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;  // 字符设备
        char            *i_link; // 不知道是啥
        unsigned        i_dir_seq; // 不知道是啥
    };
    __u32           i_generation;
#ifdef CONFIG_FSNOTIFY
    __u32           i_fsnotify_mask; /* all e
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值