zoukankan      html  css  js  c++  java
  • Linux文件系统2---VFS的四个主要对象

    1.引言

    本文所述关于文件管理的系列文章主要是对陈莉君老师所讲述的文件系统管理知识讲座的整理。

    Linux可以支持不同的文件系统,它源于unix文件系统,也是unix文件系统的一大特色。

    Linux文件系统1--概述 中我们了解了文件系统的作用,以及为了使得所有的文件系统能在同一个操作系统上工作,而产生的虚拟文件系统。

    本章我们开始分析万能的虚拟文件系统是怎么构成的,虚拟文件文件系统由四个主要的对象构成,分别是:超级块,索引结点,目录项,文件对象。

    而所谓的文件系统主要是对文件对象进行管理,那么,其余的三个结构体是用来做什么的呢?

    想一下,如果,你要查一份文件,必须要核对文件对象,那么文件对象越大,CPU则会浪费很多时间在核对上。

    所以,我们给文件对象学着外国人一样, 起了三层结构的名字,目录项--索引结点--超级块,是不是很有趣。

    2.文件系统的四个主要对象概述

    • 超级块对象

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

    • 索引节点对象

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

    • 目录项对象

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

    • 文件对象

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

    3. 超级块super_block

    3.1 struct super_block

      1 struct super_block {
      2     struct list_head    s_list;        /* Keep this first 指向超级块链表的指针*/
      3     dev_t            s_dev;        /* search index; _not_ kdev_t 具体文件系统的块设备描述符*/
      4     unsigned char        s_blocksize_bits;
      5     unsigned long        s_blocksize; /*以字节为单位的数据块的大小*/
      6     loff_t            s_maxbytes;    /* Max file size */
      7     struct file_system_type    *s_type; /*文件系统类型*/
      8     const struct super_operations    *s_op; /*指向超级块操作的函数集合*/
      9     const struct dquot_operations    *dq_op;
     10     const struct quotactl_ops    *s_qcop;
     11     const struct export_operations *s_export_op;
     12     unsigned long        s_flags;
     13     unsigned long        s_iflags;    /* internal SB_I_* flags */
     14     unsigned long        s_magic;
     15     struct dentry        *s_root;
     16     struct rw_semaphore    s_umount;
     17     int            s_count;
     18     atomic_t        s_active;
     19 #ifdef CONFIG_SECURITY
     20     void                    *s_security;
     21 #endif
     22     const struct xattr_handler **s_xattr;
     23 
     24     struct hlist_bl_head    s_anon;        /* anonymous dentries for (nfs) exporting */
     25     struct list_head    s_mounts;    /* list of mounts; _not_ for fs use */
     26     struct block_device    *s_bdev;
     27     struct backing_dev_info *s_bdi;
     28     struct mtd_info        *s_mtd;
     29     struct hlist_node    s_instances;
     30     unsigned int        s_quota_types;    /* Bitmask of supported quota types */
     31     struct quota_info    s_dquot;    /* Diskquota specific options */
     32 
     33     struct sb_writers    s_writers;
     34 
     35     char s_id[32];                /* Informational name */
     36     u8 s_uuid[16];                /* UUID */
     37 
     38     void             *s_fs_info;    /* Filesystem private info 具体文件系统的私有数据*/
     39     unsigned int        s_max_links;
     40     fmode_t            s_mode;
     41 
     42     /* Granularity of c/m/atime in ns.
     43        Cannot be worse than a second */
     44     u32           s_time_gran;
     45 
     46     /*
     47      * The next field is for VFS *only*. No filesystems have any business
     48      * even looking at it. You had been warned.
     49      */
     50     struct mutex s_vfs_rename_mutex;    /* Kludge */
     51 
     52     /*
     53      * Filesystem subtype.  If non-empty the filesystem type field
     54      * in /proc/mounts will be "type.subtype"
     55      */
     56     char *s_subtype;
     57 
     58     /*
     59      * Saved mount options for lazy filesystems using
     60      * generic_show_options()
     61      */
     62     char __rcu *s_options;
     63     const struct dentry_operations *s_d_op; /* default d_op for dentries */
     64 
     65     /*
     66      * Saved pool identifier for cleancache (-1 means none)
     67      */
     68     int cleancache_poolid;
     69 
     70     struct shrinker s_shrink;    /* per-sb shrinker handle */
     71 
     72     /* Number of inodes with nlink == 0 but still referenced */
     73     atomic_long_t s_remove_count;
     74 
     75     /* Being remounted read-only */
     76     int s_readonly_remount;
     77 
     78     /* AIO completions deferred from interrupt context */
     79     struct workqueue_struct *s_dio_done_wq;
     80     struct hlist_head s_pins;
     81 
     82     /*
     83      * Keep the lru lists last in the structure so they always sit on their
     84      * own individual cachelines.
     85      */
     86     struct list_lru        s_dentry_lru ____cacheline_aligned_in_smp;
     87     struct list_lru        s_inode_lru ____cacheline_aligned_in_smp;
     88     struct rcu_head        rcu;
     89     struct work_struct    destroy_work;
     90 
     91     struct mutex        s_sync_lock;    /* sync serialisation lock */
     92 
     93     /*
     94      * Indicates how deep in a filesystem stack this SB is
     95      */
     96     int s_stack_depth;
     97 
     98     /* s_inode_list_lock protects s_inodes */
     99     spinlock_t        s_inode_list_lock ____cacheline_aligned_in_smp;
    100     struct list_head    s_inodes;    /* all inodes 所有的inodes*/
    101 };
    • 超级块用来描述整个文件系统的信息
    • 每个具体的文件系统都有自己的超级块
    • VFS超级块是各种文件系统在安装时建立的,并在卸载时被自动删除,其数据结构是super_block
    • 所有超级块对象都以双向循环链表的形式链接在一起

    图 所有超级块链接在一起

    3.2 struct super_operations

    图 超级块对象的操作函数

    • 与超级块关联的方法就是超级块操作表,这些操作是由struct super_operations来描述

    3.3 打印超级块信息

    4.索引节点inode

     4.1 struct inode

     1 struct inode {
     2     umode_t            i_mode;
     3     unsigned short        i_opflags;
     4     kuid_t            i_uid;
     5     kgid_t            i_gid;
     6     unsigned int        i_flags;
     7 
     8 #ifdef CONFIG_FS_POSIX_ACL
     9     struct posix_acl    *i_acl;
    10     struct posix_acl    *i_default_acl;
    11 #endif
    12 
    13     const struct inode_operations    *i_op;
    14     struct super_block    *i_sb;
    15     struct address_space    *i_mapping;
    16 
    17 #ifdef CONFIG_SECURITY
    18     void            *i_security;
    19 #endif
    20 
    21     /* Stat data, not accessed from path walking */
    22     unsigned long        i_ino;
    23     /*
    24      * Filesystems may only read i_nlink directly.  They shall use the
    25      * following functions for modification:
    26      *
    27      *    (set|clear|inc|drop)_nlink
    28      *    inode_(inc|dec)_link_count
    29      */
    30     union {
    31         const unsigned int i_nlink;
    32         unsigned int __i_nlink;
    33     };
    34     dev_t            i_rdev;
    35     loff_t            i_size;
    36     struct timespec        i_atime;
    37     struct timespec        i_mtime;
    38     struct timespec        i_ctime;
    39     spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */
    40     unsigned short          i_bytes;
    41     unsigned int        i_blkbits;
    42     blkcnt_t        i_blocks;
    43 
    44 #ifdef __NEED_I_SIZE_ORDERED
    45     seqcount_t        i_size_seqcount;
    46 #endif
    47 
    48     /* Misc */
    49     unsigned long        i_state; /*索引节点的状态标志*/
    50     struct mutex        i_mutex;
    51 
    52     unsigned long        dirtied_when;    /* jiffies of first dirtying */
    53     unsigned long        dirtied_time_when;
    54 
    55     struct hlist_node    i_hash; /*指向哈希链表的指针*/
    56     struct list_head    i_io_list;    /* backing dev IO list */
    57 #ifdef CONFIG_CGROUP_WRITEBACK
    58     struct bdi_writeback    *i_wb;        /* the associated cgroup wb */
    59 
    60     /* foreign inode detection, see wbc_detach_inode() */
    61     int            i_wb_frn_winner;
    62     u16            i_wb_frn_avg_time;
    63     u16            i_wb_frn_history;
    64 #endif
    65     struct list_head    i_lru;        /* inode LRU list 指向索引节点链表的指针*/
    66     struct list_head    i_sb_list; /*指向超级块的指针*/
    67     union {
    68         struct hlist_head    i_dentry;
    69         struct rcu_head        i_rcu;
    70     };
    71     u64            i_version;
    72     atomic_t        i_count;
    73     atomic_t        i_dio_count;
    74     atomic_t        i_writecount;
    75 #ifdef CONFIG_IMA
    76     atomic_t        i_readcount; /* struct files open RO */
    77 #endif
    78     const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */
    79     struct file_lock_context    *i_flctx;
    80     struct address_space    i_data;
    81     struct list_head    i_devices;
    82     union {
    83         struct pipe_inode_info    *i_pipe;
    84         struct block_device    *i_bdev;
    85         struct cdev        *i_cdev;
    86         char            *i_link;
    87     };
    88 
    89     __u32            i_generation;
    90 
    91 #ifdef CONFIG_FSNOTIFY
    92     __u32            i_fsnotify_mask; /* all events this inode cares about */
    93     struct hlist_head    i_fsnotify_marks;
    94 #endif
    95 
    96     void            *i_private; /* fs or device private pointer */
    97 };
    • 文件系统处理文件所需要的所有信息都保存在称为索引节点的inode结构体中
    • 同一个文件系统中,每个文件的索引节点号都是唯一的
    • 与索引节点关联的方法由struct inode_operations来描述
    • inode有两个设备号:i_dev(常规文件的设备号),i_rdev(某一设备的设备号)
    • LInux文件系统的另外一大特色:设备即文件。驱动中设备号的来源

     4.2  struct inode_operations

    图 索引节点的操作函数

    5.目录项dentry

    5.1 struct dentry

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

    5.2  struct dentry_operations

    图 目录项的操作函数

    6. 文件对象(file)

    6.1 struct file

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

     6.2 struct file_operations

    6.3  struct files_struct

    • 文件描述符用来描述打开的文件
    • 每个进程用一个files_struct结构来记录文件描述符的使用情况
    • 这个files_stuct结构称为用户打开文件表,它是进程的私有数据

     

    图 用户打开文件表

    6.4 struct fs_struct

    8    struct fs_struct {
    9        int users;
    10        spinlock_t lock;
    11        seqcount_t seq;
    12        int umask;  //用于为新创建的文件设置初始文件许可权限
    13        int in_exec;
    14        struct path root, pwd;
    15    };
    • 描述进程与文件系统的关系

     7. 主要数据结构之间的关系

    图 主要数据结构之间的关系

    • 超级块是对一个文件系统的描述
    • 索引节点是对一个文件物理属性的描述
    • 目录项是对一个文件逻辑属性的描述
    • 一个进程所处的位置由fs_struct描述
    • 一个进程(或用户)打开的文件由files_struct描述
    • 整个系统所打开的文件由 file结构来描述
  • 相关阅读:
    洛谷P3157 [CQOI2011]动态逆序对
    CDQ分治
    快速数论变换(NTT)
    洛谷P3338 [ZJOI2014]力
    洛谷 P1919 A*B Problem升级版
    0-1分数规划
    洛谷P4593 [TJOI2018]教科书般的亵渎
    拉格朗日插值
    20180912-3 词频统计
    20190912-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/smartjourneys/p/7260911.html
Copyright © 2011-2022 走看看