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

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

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

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

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. 创建软链接时,链接计数i_nlink不会增加;

6. 删除软链接不会影响被指向的文件,但若指向的原文件被删除,则成死链接,但重新创建指向 的路径即可恢复为正常的软链接,只是源文件的内容可能变了。

file:每一个打开的文件都对应一个file结构,还保存文件的打开方式和偏移等。

struct file { 
    /* 
     * fu_list becomes invalid after file_free is called and queued via 
     * fu_rcuhead for RCU freeing 
     */ 
    union { 
        struct list_head    fu_list; 
        struct rcu_head     fu_rcuhead; 
    } f_u; 
    struct path        f_path; 
#define f_dentry    f_path.dentry 
#define f_vfsmnt    f_path.mnt 
    const struct file_operations    *f_op; 
    atomic_t        f_count; 
    unsigned int         f_flags; 
    mode_t            f_mode; 
   loff_t            f_pos; 
    struct fown_struct    f_owner; 
    unsigned int        f_uid, f_gid; 
    struct file_ra_state    f_ra;

unsigned long        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; 
    spinlock_t        f_ep_lock; 
#endif /* #ifdef CONFIG_EPOLL */ 
    struct address_space    *f_mapping; 
};

注意:VFS文件系统中的inode和dentry与实际文件系统的inode和dentry有一定的关系,但不能等同。真实磁盘文件的inode和dentry是存在于物理外存上的,但VFS中的inode和dentry是存在于内存中的,系统读取外存中的inode和dentry信息进行一定加工后,生成内存中的inode和dentry。虚拟的文件系统也具有inode和dentry结构,只是这是系统根据相应的规则生成的,不存在于实际外存中。

对应外存上的实际文件系统在格式化时就划分出了inode的数目和数据区块的数量,所以有可能inode用完了但数据区块还有剩余空间的情况。即虽然磁盘仍有剩余空间,但不能再创建文件和目录。

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

  1. 解析 Linux 中的 VFS 文件系统机制

    简介: 本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2.4.20 内核.总体上说 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 V ...

  2. 解析linux中的vfs文件系统机制,解析Linux中的VFS文件系统机制

    解析Linux中的VFS文件系统机制 本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2.4.20 内核.总体上说Linux下的文件系统主要可分为三大块:一是上层的文件系统的系统 ...

  3. 解析Linux中的VFS文件系统机制

    文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2.4.20 内核.总体上说Linux下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 VFS(Virt ...

  4. 解析 Linux 中的 VFS 文件系统机制(1)

    住:这里只转载一篇,还有几篇没有转载,但这里给出源地址: http://www.51cto.com/art/200803/67283.htm 摘要:本文阐述 Linux 中的文件系统部分,源代码来自基 ...

  5. linux文件系统dentry_文件系统中超级块、inode和dentry三者的分析

    原标题:文件系统中超级块.inode和dentry三者的分析 文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 而随着文件种类的增多,扩增了更多的文件系统,为了对各种文件系统进 ...

  6. Linux内核中的vfs,解析 Linux 中的 VFS 文件系统机制

    在Linux系统中,每个分区都是一个文件系统,都有自己的目录层次结构.Linux的最重要特征之一就是支持多种文件系统,这样它更加灵 活,并可以和许多其它种操作系统共存.由于系统已将Linux文件系统的 ...

  7. linux中vfs和fs区别,解析Linux中的 VFS 文件系统机制(rootfs)一

    本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2.4.20 内核.总体上说 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 VFS(V ...

  8. Linux文件系统中的inode节点详细介绍

    一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...

  9. 以下关于linux文件系统中inode,linux文件系统—inode及相关概念.docx

    linux文件系统-inode及相关概念 linux文件系统-inode及相关概念 博客分类: /category/156693Linux/blogs/tag/LinuxLinux/blogs/tag ...

  10. 硬核解析Linux文件系统底层【VFS文件系统】

    Linux VFS文件系统 Linux一直强调一切皆文件,除了普通的文件和目录,块设备.管道.socket等都被Linux视为文件.所以理解了文件系统,对于深入理解Linux非常重要,接下来就让我们从 ...

最新文章

  1. mysql程序语句范文,SQL语句(MySQL)
  2. 解压Ubuntu的initrd.img的方法
  3. 编程游戏python我的世界_乐学Python编程-做个游戏很简单
  4. unipapp 解决无法编译sass_如何解决Vue项目里面没有sassloader依赖包的问题
  5. 静态类 c# 1614532739
  6. Enterprise Library访问Access数据库
  7. Xlua中的util脚本中的async_to_sync方法 记录
  8. datatables ajax错误,ajax datatable - DataTables警告:table id = example - 无法重新初始化DataTable(示例代码)...
  9. stats | 介绍三个与数学规划函数
  10. matlab 自带pca函数,matlab实现主成分分析 princomp函数 PCA中有这个函数
  11. js中字符串全部替换函数(正则表达式)
  12. 2020 安装 nacos
  13. java中连接数据库
  14. 单片机毕业设计不用愁!!30篇单片机毕业设计参考案例
  15. GTX1050安装cuda10.2配置pytorch正确指令
  16. animation停留_animation控制动画暂停/播放
  17. 《基于深度学习的加密流量识别研究》-2022毕设笔记
  18. 移动硬盘文件丢失如何找回丨500G硬盘
  19. 要点初见:双硬盘下的Win10+Ubuntu16.04双系统安装
  20. 租用游艇问题(pta)

热门文章

  1. hdu 1072 Nightmare BFS搜索(可重走)
  2. HTML中构建自动伸缩的表格Table
  3. go语言渐入佳境[10]-function
  4. 在阿里云创建子域名,配置nginx,使用pm2部署node项目到ubuntu服务器
  5. Redis 中的事件驱动模型
  6. 重磅!Intel联合OpenStack基金会发布Kata Container项目
  7. 控制文件丢失的恢复(续)
  8. 360与Bing合作上线英文搜索
  9. 转 web 开发字体
  10. C核心技术手册(四十五)