关于VFS文件系统中的superblock、inode、d_entry和file数据结构

来源:互联网 发布:网页标题优化百度百科 编辑:程序博客网 时间:2024/06/06 01:28

Linux下的文件系统中宏观上主要分为三层:一是上层的文件系统的系统调用;二是虚拟文件系统VFS(Virtual File System)层,三是挂载到VFS中的各种实际文件系统。

         VFS是一种软件机制,只存在于内存中,每次系统初始化期间Linux都会先在内存中构造一棵VFS的目录树(也就是源码中的namespace)。VFS主要的作用是对上层应用屏蔽底层不同的调用方法,提供�%8 套统一的调用接口,二是便于对不同的文件系统进行组织管理。因此,VFS其实就是文件系统组织管理中的一个抽象层。

EQK69W`U%7%`FRO61DU0R9C

一个典型的VFS目录组织方式如下图所示:

5S_DM2]{U`G]59`AM`TL~33

Superblock:超级块,是文件系统最基本的元数据,它定义了文件系统的类型、大小、状态和其他信息等。Superblock对于文件系统是非常关键的,因此一般文件系统都会冗余存储多份。

~X]L$2J}4}KSS`5OE)MG~`F

struct super_block { 
    struct list_head    s_list;        /* 系统将所有文件系统的超级块组成链表*/ 
    dev_t            s_dev;        /* search index; _not_ kdev_t */ 
    unsigned long        s_blocksize; 
    unsigned char        s_blocksize_bits; 
    unsigned char        s_dirt; 
    unsigned long long    s_maxbytes;    /* Max file size */ 
    struct file_system_type    *s_type; //文件系统类型 
    const struct super_operations    *s_op; //操作函数集 
    struct dquot_operations    *dq_op; 
     struct quotactl_ops    *s_qcop; 
    struct export_operations *s_export_op; 
    unsigned long        s_flags; 
    unsigned long        s_magic; 
    struct dentry        *s_root; //挂载根目录 
    struct rw_semaphore    s_umount; 
    struct mutex        s_lock; 
    int            s_count; 
    int            s_syncing; 
    int            s_need_sync_fs; 
    atomic_t        s_active; 
#ifdef CONFIG_SECURITY 
    void                    *s_security; //LSM框架的安全域 
#endif 
    struct xattr_handler    **s_xattr;

    struct list_head    s_inodes;    /* 所有的inode节点链表*/ 
    struct list_head    s_dirty;    /* dirty inodes */ 
    struct list_head    s_io;        /* parked for writeback */ 
    struct hlist_head    s_anon;        /* anonymous dentries for (nfs) exporting */ 
    struct list_head    s_files;

    struct block_device    *s_bdev; 
    struct list_head    s_instances; 
    struct quota_info    s_dquot;    /* Diskquota specific options */

    int            s_frozen; 
    wait_queue_head_t    s_wait_unfrozen;

    char s_id[32];                /* Informational name */

    void             *s_fs_info;    /* Filesystem private info */

    /* 
     * 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 */

    /* Granularity of c/m/atime in ns. 
       Cannot be worse than a second */ 
    u32           s_time_gran; 
};

 

inode:包含了一个文件的元数据,如文件所在数据块等。这里需要注意Linux中的所有对象均为文件:实际的文件、目录、设备等等。一个inode基本包含:所有权(用户、组)、访问模式(读、写、执行)和文件类型等,但不包含文件名。

struct inode { 
    struct hlist_node    i_hash; 
    struct list_head    i_list; 
    struct list_head    i_sb_list; //链入超级块中的链表 
    struct list_head    i_dentry; 
    unsigned long        i_ino;
 //节点号 
    atomic_t        i_count; //引用计数 
    unsigned int        i_nlink;  //硬链接数目 
    uid_t            i_uid;  //表示文件所有者
    gid_t            i_gid;  //表示文件所有者所属组
    dev_t            i_rdev; 
    unsigned long        i_version; 
    loff_t            i_size; 
#ifdef __NEED_I_SIZE_ORDERED 
    seqcount_t        i_size_seqcount; 
#endif 
    struct timespec        i_atime; 
    struct timespec        i_mtime; 
    struct timespec        i_ctime; 
    unsigned int        i_blkbits; 
    blkcnt_t        i_blocks; 
    unsigned short          i_bytes; 
    umode_t            i_mode;  //inode权限
    spinlock_t        i_lock;    /* i_blocks, i_bytes, maybe i_size */ 
    struct mutex        i_mutex; 
    struct rw_semaphore    i_alloc_sem; 
    const struct inode_operations    *i_op;  //inode操作函数集
    const struct file_operations    *i_fop;    /* former ->i_op->default_file_ops */ 
    struct super_block    *i_sb; //指向超级块 
    struct file_lock    *i_flock; 
    struct address_space    *i_mapping; 
    struct address_space    i_data; 
#ifdef CONFIG_QUOTA 
    struct dquot        *i_dquot[MAXQUOTAS]; 
#endif 
    struct list_head    i_devices; 
    union { 
        struct pipe_inode_info    *i_pipe; 
        struct block_device    *i_bdev; 
        struct cdev        *i_cdev; 
    }; 
    int            i_cindex;

    __u32            i_generation;

#ifdef CONFIG_DNOTIFY 
    unsigned long        i_dnotify_mask; /* Directory notify events */ 
    struct dnotify_struct    *i_dnotify; /* for directory notifications */ 
#endif

#ifdef CONFIG_INOTIFY 
    struct list_head    inotify_watches; /* watches on this inode */ 
    struct mutex        inotify_mutex;    /* protects the watches list */ 
#endif

    unsigned long        i_state; 
    unsigned long        dirtied_when;    /* jiffies of first dirtying */

    unsigned int        i_flags;

    atomic_t        i_writecount; 
#ifdef CONFIG_SECURITY 
    void            *i_security; //LSM框架中的安全域 
#endif 
    void            *i_private; /* fs or device private pointer */ 
};

inode结构中的i_ino索引节点号在同一个文件系统中是唯一的,但若是系统中挂载了多个文件系统,则inode号可能出现相同的情况。

其中这个 i_mode是16位的无符号整数表示,由9位权限方式位、3位“粘滞”标志位和4位文件类型标志位,它们的具体的定义在 include/linux/stat.h中:

#define S_IFMT   00170000     /* 用于抽取i_mode域中类型部分的屏蔽位 */
#define S_IFSOCK 0140000     /* 套接字类型码 */
#define S_IFLNK    0120000    /* 符号连接类型码 */
#define S_IFREG   0100000    /* 普通文件类型码 */
#define S_IFBLK   0060000    /* 块特别文件类型码 */
#define S_IFDIR   0040000     /* 目录文件类型码 */
#define S_IFCHR   0020000    /* 字符特别文件类型码 */
#define S_IFIFO   0010000     /* 管道或FIFO类型码 */
#define S_ISUID   0004000    /* 用户粘滞位 */
#define S_ISGID   0002000    /* 用户组粘滞位 */
#define S_ISVTX   0001000   /* 粘滞位 */
#define S_IRWXU 00700     /* 用户读写执行 */
#define S_IRUSR 00400      /* 用户读 */
#define S_IWUSR 00200     /* 用户写 */
#define S_IXUSR 00100     /* 用户执行 */
#define S_IRWXG 00070    /* 用户组读写执行 */
#define S_IRGRP 00040    /* 用户组读 */
#define S_IWGRP 00020    /* 用户组写 */
#define S_IXGRP 00010    /* 用户组执行 */
#define S_IRWXO 00007   /* 其他用户读写执行 */
#define S_IROTH 00004    /* 其他用户读 */
#define S_IWOTH 00002   /* 其他用户写 */
#define S_IXOTH 00001   /* 其他用户执行 */
#define S_IRWXUGO     (S_IRWXU|S_IRWXG|S_IRWXO)   /* 全部用户读写执行 */
#define S_IALLUGO      (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO )/* 全部用户全部权限 */
#define S_IRUGO          (S_IRUSR|S_IRGRP|S_IROTH)    /* 全部用户读 */
#define S_IWUGO         (S_IWUSR|S_IWGRP|S_IWOTH)   /* 全部用户写 */
#define S_IXUGO          (S_IXUSR|S_IXGRP|S_IXOTH)    /* 全部用户执行 */

dentry:将inode号和文件名联系起来,dentry还保存目录和其子对象的关系,用于文件系统的变量。dentry还起着缓存的作用,缓存最常使用的文件以便于更快捷的访问。

struct dentry { 
    atomic_t d_count; //引用计数 
    unsigned int d_flags;        /* protected by d_lock */ 
    spinlock_t d_lock;        /* per dentry lock */ 
   struct inode *d_inode;        /* Where the name belongs to - NULL is 
                     * negative */ 
    /* 
     * The next three fields are touched by __d_lookup.  Place them here 
     * so they all fit in a cache line. 
     */ 
    struct hlist_node d_hash;    /* lookup hash list */ 
    struct dentry *d_parent;    /* parent directory */ 
   struct qstr d_name;  //目录项名称,与inode对应起来

    struct list_head d_lru;        /* LRU list */ 
    /* 
     * d_child and d_rcu can share memory 
     */ 
    union { 
        struct list_head d_child;    /* child of parent list */ 链入父目录的子目录中 
         struct rcu_head d_rcu; 
    } d_u; 
    struct list_head d_subdirs;    /* our children */ 子目录链表 
   struct list_head d_alias;    /* inode alias list */ 链入inode节点的i_dentry链表,因为一个inode可能对应多个dentry(硬链接) 
    unsigned long d_time;        /* used by d_revalidate */ 
    struct dentry_operations *d_op; 
    struct super_block *d_sb;    /* The root of the dentry tree */ 
    void *d_fsdata;            /* fs-specific data */ 
#ifdef CONFIG_PROFILING 
    struct dcookie_struct *d_cookie; /* cookie, if any */ 
#endif 
    int d_mounted; 
    unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* small names */ 
};

 

在内存中,每个文件都有一个dentry(目录项)和inode(索引节点)结构,dentry记录文件名、父目录、子目录等信息,形成文件树结构。inode结构则包含文件的宿主、创建时间和在存储介质上的位置和分布等信息。其中每个dentry都有一个唯一的inode,而每个inode则可能有多个dentry,这种情况是由ln硬链接产生的。

硬链接:其实就是同一个文件具有多个别名,具有相同inode,而dentry不同。

              1. 文件具有相同的inode和data block;

              2. 只能对已存在的文件进行创建;

              3. 不同交叉文件系统进行硬链接的创建

              4. 不能对目录进行创建,只能对文件创建硬链接

              5. 删除一个硬链接并不影响其他具有相同inode号的文件;

软链接:软链接具有自己的inode,即具有自己的文件,只是这个文件中存放的内容是另一个文件的路径名。因此软链接具有自己的inode号以及用户数据块。

              1. 软链接有自己的文件属性及权限等;

              2. 软链接可以对不存在的文件或目录创建;

              3. 软链接可以交叉文件系统;

              4. 软链接可以对文件或目录创建;

              5. 创建软链接时,链接计%E

0 0