Linux内核文件系统-虚拟文件系统-超级块对象

建议点击这里查看个人主页上的最新原文

点击这里在哔哩哔哩bilibili在线观看配套的教学视频

点击这里在哔哩哔哩bilibili在线观看配套的加餐视频(就是一些补充)

点击跳转到内核课程所有目录

一般的Linux书籍都是先讲解进程和内存相关的知识,但我想先讲解文件系统。第一,因为我就是做文件系统的,更擅长这一块,其他模块的内容我还要再去好好看看书,毕竟不能误人子弟嘛;第二,是因为文件系统模块更接近于用户态,是相对比较好理解的内容(当然想深入还是要下大功夫的),由文件系统入手比较适合初学者。

虚拟文件系统英文全称Virtual file system,缩写为VFS,又称为虚拟文件切换系统(virtual filesystem switch)。所有的文件系统都要先经过虚拟文件系统层,虚拟文件系统相当于制定了一套规则,如果你想写一个新的文件系统,只需要遵守这套规则就可以了。

VFS虽然是用C语言写的,但使用了面向对象的设计思路。

超级块英文全称是super block,存储特定文件系统的信息。如果是基于磁盘的文件系统,通常对应磁盘上特定扇区中的数据。如果不是基于磁盘的文件系统(如procfs或sysfs),会在使用时创建超级块,只保留在内存中。

超级块对象结构体定义在文件include/linux/fs.h中,比较长,不用背,用到时查一下就好,我会在这里加一些中文注释。

struct super_block {
        struct list_head        s_list;         /* 放在最开头,指向 super_blocks,使用list_add_tail加到super_blocks链表中 */
        dev_t                   s_dev;          /* 设备标识符 */
        unsigned char           s_blocksize_bits; // 块大小,单位: bit
        unsigned long           s_blocksize; // 块大小,单位: 字节
        loff_t                  s_maxbytes;     /* 文件大小上限 */
        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;       /* 内部 SB_I_* 标志 */
        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; // 扩展的属性操作
#ifdef CONFIG_FS_ENCRYPTION
        const struct fscrypt_operations *s_cop;
        struct fscrypt_keyring  *s_master_keys; /* 主加密密钥正在使用 */
#endif
#ifdef CONFIG_FS_VERITY
        const struct fsverity_operations *s_vop;
#endif
#if IS_ENABLED(CONFIG_UNICODE)
        struct unicode_map *s_encoding;
        __u16 s_encoding_flags;
#endif
        struct hlist_bl_head    s_roots;        /* NFS 的备用根目录项 */
        struct list_head        s_mounts;       /* 挂载点列表;_不_用于文件系统,struct mount的mnt_instance加到这个链表中 */
        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;  /* 支持的配额类型的位掩码 */
        struct quota_info       s_dquot;        /* 限额相关选项 */

        struct sb_writers       s_writers;

        /*
         * 将 s_fs_info, s_time_gran, s_fsnotify_mask 和
         * s_fsnotify_marks 放在一起以提高缓存效率。
         * 它们经常被访问但很少被修改。
         */
        void                    *s_fs_info;     /* 文件系统私有信息 */

        /* c/m/atime 的精度(以纳秒为单位,不能超过一秒) */
        u32                     s_time_gran; // 时间戳粒度
        /* c/m/atime 的时间限制(以秒为单位) */
        time64_t                   s_time_min;
        time64_t                   s_time_max;
#ifdef CONFIG_FSNOTIFY
        __u32                   s_fsnotify_mask;
        struct fsnotify_mark_connector __rcu    *s_fsnotify_marks;
#endif

        char                    s_id[32];       /* 信息性名称,文本名字 */
        uuid_t                  s_uuid;         /* Universally Unique Identifier"(全局唯一标识符) */

        unsigned int            s_max_links;

        /*
         * 下一个字段仅供 VFS 使用。任何文件系统都没有权利查看它。
         * 你已经被警告过了。
         */
        struct mutex s_vfs_rename_mutex;        /* Kludge,重命名锁 */

        /*
         * 文件系统子类型。如果非空,/proc/mounts 中的文件系统类型字段
         * 将是 "type.subtype"
         */
        const char *s_subtype; // 子类型名称

        const struct dentry_operations *s_d_op; /* 目录项的默认 d_op */

        struct shrinker s_shrink;       /* 每个超级块的收缩器句柄 */

        /* nlink == 0 但仍被引用的 inode 数量 */
        atomic_long_t s_remove_count;

        /*
         * 被监视的 inode/mount/sb 对象的数量,注意 inode 对象目前被双重计算。
         */
        atomic_long_t s_fsnotify_connectors;

        /* 超级块的只读状态正在被更改 */
        int s_readonly_remount;

        /* 每个超级块的 errseq_t 用于通过 syncfs 报告回写错误 */
        errseq_t s_wb_err;

        /* 从中断上下文推迟的 AIO 完成 */
        struct workqueue_struct *s_dio_done_wq;
        struct hlist_head s_pins;

        /*
         * 拥有的用户命名空间和默认上下文,用于解释文件系统的 uid、gid、配额、
         * 设备节点、xattrs 和安全标签。
         */
        struct user_namespace *s_user_ns;

        /*
         * list_lru 结构本质上只是指向每个节点 lru 列表表格的指针,
         * 每个节点都有自己的自旋锁。没有必要将它们放入不同的缓存行。
         */
        struct list_lru         s_dentry_lru; // 未被使用目录项链表
        struct list_lru         s_inode_lru;
        struct rcu_head         rcu;
        struct work_struct      destroy_work;

        struct mutex            s_sync_lock;    /* 同步序列化锁 */

        /*
         * 指示该超级块在文件系统栈中的深度
         */
        int s_stack_depth;

        /* s_inode_list_lock 保护 s_inodes */
        spinlock_t              s_inode_list_lock ____cacheline_aligned_in_smp;
        struct list_head        s_inodes;       /* 索引节点链表 */

        spinlock_t              s_inode_wblist_lock;
        struct list_head        s_inodes_wb;    /* 回写的 inode */
} __randomize_layout;

超级块对象通过alloc_super()函数创建和初始化,具体的文件系统如ext2文件系统的流程如下:

mount // 系统调用
  do_mount
    path_mount
      do_new_mount
        vfs_get_tree
          legacy_get_tree
            ext2_mount // ext2_fs_type的.mount方法
              mount_bdev
                sget
                  alloc_super
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值