linux文件系统:VFS

文章目录

  • vfs
    • 1 super_block
    • 2 dentry
      • 2.1 dentry树
      • 2.2 dentry的cache
      • 2.3 挂载
    • 3 inode
    • 4 文件file
    • 5 vfs各结构体的关系

vfs

Linux内核通过虚拟文件系统(Virtual File System,VFS)管理文件系统

VFS为所有的文件系统提供了统一的接口,对每个具体文件系统的访问要通过VFS定义的接口来实现

VFS本身只存在于内存中,它需要将硬盘上的文件系统抽象到内存中,这个工作是通过几个重要的结构实现的:

  • dentry
  • inode
  • super_block
  • file

1 super_block

超级块(super_block)代表了整个文件系统本身。通常,超级块是对应文件系统自身的控制块结构,其内容需要读取文件系统在硬盘上的超级块结构获得,所以超级块是具体文件系统超级块的内存抽象。

超级块简略结构如下:

struct super_block {
        unsigned long        s_blocksize;            /* 文件系统的块大小 */
        unsigned char        s_blocksize_bits;
        ……/*省略超级块的链表、设备号等代码*/
        unsigned long long        s_maxbytes;        /* Max file size */

        struct file_system_type        *s_type;
        struct super_operations        *s_op;    /* 提供了一些重要的超级块操作函数 */

        unsigned long        s_magic;            /* 每个文件系统都有一个magic */
        struct dentry        *s_root;            /* 指向文件系统根dentry的指针 */

        struct list_head        s_inodes;        /* 包含文件系统内所有的 inodes */
        struct list_head        s_dirty;         /* dirty inodes */

        struct block_device        *s_bdev;      /* 指向文件系统存在的块设备指针 */
        void         *s_fs_info;                 /* Filesystem private info */
};

参考include/linux/fs.h

每个文件系统都有一个超级块结构,每个超级块都要链接到一个超级块链表。

ext4_super_block
super_block
ufs_super_block
squashfs_super_block

文件系统内的每个文件在打开时都需要在内存分配一个inode结构,这些inode结构都要链接到超级块。

顺着super_blocks链表可以遍历整个操作系统打开过的文件的inode结构。

2 dentry

对于一个通常的文件系统来说,文件和目录一般按树状结构保存,目录项(dentry)就是反映了文件系统的这种树状关系。

2.1 dentry树

在VFS里,目录本身也是一个文件,只是有点特殊。每个文件都有一个dentry,这个dentry链接到上级目录的dentry,这样层层链接形成了目录树。

dentry-subdir_child

dentry简略结构如下:

struct dentry {
 ……/省略dentry锁、标志等代码/
    struct inode *d_inode;        /* 指向一个inode结构。这个inode和dentry共同描述了一个普通文件或者目录文件 */
    /*
     * 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;           /* 链接到dentry cache的hash链表 */
    struct dentry *d_parent;            /* parent directory */
    struct qstr d_name;                 /* 文件或目录的名字 */

    /*
     * 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;        /* 子项的链表头,所有子项d_child都要链接到这个链表 */

    struct dentry_operations *d_op;
    struct super_block *d_sb;          /* The root of the dentry tree */
    int d_mounted;                     /* 指示dentry是否是一个挂载点,如果是则不为0 */
};

参考include/linux/fs.h

2.2 dentry的cache

所有的dentry都指向一个dentry_hashtabledentry_hashtable是个数组,它的数组成员是hash链表数据结构。

dentry__hashtable

这里所说的dentry,指的是在内存中的dentry。
如果某个文件已经被打开过,内存中就应该有该文件的dentry结构,并且该dentry被链接到dentry_hashtable数组的某个hash链表头。
后续再访问该文件的时候,就可以直接从hash链表里面找到,避免了再次读硬盘。这是dentry的cache概念。

2.3 挂载

通过dentry的d_mounted成员不为0可以判断: 该目录不是一个普通的目录,而是一个文件系统的挂载点。

在一开始,根文件系统和要挂载的源文件系统分别有两个dentry树。
当文件系统被挂载的时候,它的vfsmount结构就被链接到内核的一个全局链表—mount_hashtable数组链表。

每个文件系统都有这样一个vfsmount结构

当发现mnt目录是个特殊的目录时,从mount_hashtable数组找到hash链表头,再遍历整个hash链表,就能找到txt文件所在文件系统的vfsmount,然后mnt目录的dentry就被替换,置换为新文件系统的根目录。

3 inode

inode代表一个文件。inode保存了文件的大小、创建时间、文件的块大小等参数,以及对文件的读写函数、文件的读写缓存等信息。

具体文件系统的inode(静态节点)存储在硬盘中,在使用时需要调入内存,填写vfs的inode(动态节点)

一个真实的文件可以有多个dentry,因为指向文件的路径可以有多个(考虑文件的链接),而inode只有一个。

dentry-inode

inode简略结构如下:

struct inode {
        struct list_head        i_list;             /* 用于描述inode当前状态的链表*/
        struct list_head        i_sb_list;          /* 用于链接到超级块中的inode链表 */
        struct list_head        i_dentry;           /* 该文件的所有dentry需要链接到i_dentry */
        unsigned long           i_ino;              /* inode号 */
        atomic_t                i_count;            /* inode引用计数 */
        loff_t                  i_size;             /* 字节为单位的文件长度 */
        
        unsigned int            i_blkbits;          /* 文件块的位数 */
        struct inode_operations         *i_op;
        const struct file_operations    *i_fop;         /* former ->i_op->default_file_ops */
        struct address_space            *i_mapping;     /* 用于缓存文件的内容,便于快速读写 */
        struct block_device             *i_bdev;        /* 指向文件系统所绑定的块设备 */
  ……/*省略锁等代码*/
};

参考include/linux/fs.h

当创建一个新的inode的时候,成员i_list要链接到inode_in_use这个链表,表示inode处于使用状态,同时成员i_sb_list也要链接到文件系统超级块的s_inodes链表头。

内核提供了一个hash链表数组inode_hashtable,所有的inode结构都要链接到数组里面的某个hash链表

inode结构的i_mode成员用不同的值代表不同的文件类型:

imode类型
S_IFBLK块设备
S_IFCHR字符设备
S_IFDIR目录
S_IFSOCKsocket
S_IFIFOFIFO

4 文件file

文件对象的作用是描述进程和文件交互的关系。

这里需要指出的是,硬盘上并不存在一个文件结构。进程打开一个硬盘上的文件时,内核就动态创建一个文件对象,返回一个文件描述符,并保存文件指针到文件描述符表里面的数组。

同一个文件,在不同的进程中有不同的文件对象.

file简略结构如下:

struct file {
    struct dentry           *f_dentry;          /* 指向文件对应的dentry结构 */
    struct vfsmount         *f_vfsmnt;          /* 指向文件所属于的文件系统的vfsmount对象 */
    const struct file_operations    *f_op;   
    atomic_long_t		f_count;                     /* 使用此结构体的进程数量 */
    ……/*省略部分代码*/
    loff_t                  f_pos;              /* 表示进程对文件操作的位置。如读取前10字节,f_pos就指示第11字节位置 */
    struct fown_struct          f_owner;
    unsigned int                f_uid, f_gid;
    struct file_ra_state        f_ra;           /* 用于文件预读的设置 */

    struct address_space        *f_mapping;     /* 指向一个address_space结构。这个结构封装了文件的读写缓存页面 */
};

参考include/linux/fs.h

files_struct:用于记录进程中文件描述符的使用情况,是进程的私有数据

/*
 * Open file table structure
 */
struct files_struct {
  /*
   * read mostly part
   */
	atomic_t count;                                     /* 共享该表的进程数量 */
	bool resize_in_progress;                            /* 指示是否正在进行扩容操作 */
	wait_queue_head_t resize_wait;                      /* 等待队列头,扩容时阻塞等待的进程 */

	struct fdtable __rcu *fdt;                          /* 指向一个文件描述符表的指针 */
	struct fdtable fdtab;                               /* 文件描述符表 */
  /*
   * written part on a separate cache line in SMP
   */
	spinlock_t file_lock ____cacheline_aligned_in_smp;  /* 保护如下所有的域 */
	unsigned int next_fd;
	unsigned long close_on_exec_init[1];                /* exec()关闭文件描述符的初始值 */
	unsigned long open_fds_init[1];
	unsigned long full_fds_bits_init[1];
	struct file __rcu * fd_array[NR_OPEN_DEFAULT];      /* 文件描述符数组,存储每个打开的文件对应的file结构体指针 */
};

参考include/linux/fdtable.h

fs_struct表示文件系统信息的结构体:

struct fs_struct {
	int users;              /* 表示有多少用户正在使用该fs_struct */
	spinlock_t lock;
	seqcount_t seq;         /* 一个序列号计数器,用于维护fs_struct的序列化访问 */
	int umask;              /* 代表用户文件屏蔽掩码,用于设置新创建文件的默认权限 */
	int in_exec;            /* 指示当前进程是否正在执行 */
	struct path root, pwd;  /* 根目录 当前目录 */
} __randomize_layout;

参考include/linux/fd_struct.h

5 vfs各结构体的关系

vfs结构体之间的关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/504324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法沉淀——动态规划篇(子数组系列问题(上))

算法沉淀——动态规划篇(子数组系列问题(上)) 前言一、最大子数组和二、环形子数组的最大和三、乘积最大子数组四、乘积为正数的最长子数组长度 前言 几乎所有的动态规划问题大致可分为以下5个步骤,后续所有问题分析都…

Available platform plugins are: linuxfb, minimal, offscreen, vnc.

说明: buildroots根文件中已经移植好了QT的库,但是运行QT交叉编译之后的可执行文件报错: qt.qpa.plugin: Could not find the Qt platform plugin "eglfs" in "" This application failed to start because no Qt platf…

P4995 跳跳!(贪心)

多么痛的领悟&#xff01;大数据要开long long&#xff01;&#xff01;&#xff01;简单longlong就AC&#xff01; 代码1&#xff1a; #include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<cmath> using name…

哪种排序算法在不同情况下性能最好?

哪种排序算法在不同情况下性能最好&#xff1f;&#x1f50d;&#x1f4ca; 哪种排序算法在不同情况下性能最好&#xff1f;&#x1f50d;&#x1f4ca;&#x1f4dd; 摘要&#x1f680; 引言&#x1f4cb; 正文内容&#xff08;详细介绍&#xff09;冒泡排序快速排序&#x1f…

基于ssm旅游资源网站(java项目+文档+源码)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的旅游资源网站。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 旅游资源网站的主要使用者分为管理…

RK3588平台开发系列讲解(I2C开发篇)

目录 前言 I2C 流程 Trasmint only mode(I2C_CON[1:0]2’b00) Mix mode (I2C_CON[1:0]2’b01 or I2C_CON[1:0]2’b11) Receive only mode (I2C_CON[1:0]2’b10) I2C 驱动参数配置 I2C 使用 1 Kernel space 2User space GPIO 模拟 I2C I2C 常见问题 前言 ROCKCHIP 系…

四、戴尔R630本地服务器Linux Centos7.9系统安装docker-ce-20.10.10-3.el7版本

如需查阅上一步骤,请点击下面链接:3、Linux Centos7.9系统的iDRAC远程管理、网络设置、SecureCRT远程登录终端、企业级静态ip地址配置-CSDN博客文章浏览阅读898次,点赞17次,收藏15次。iDRAC连接登录服务器远程管理。https://blog.csdn.net/weixin_67440240/article/details…

【Anaconda】Linux下Anaconda安装和虚拟环境配置

Linux下Anaconda安装和虚拟环境配置 一、安装anaconda二、conda虚拟环境管理三、jupyter相关启动部署四、遇到问题 下面介绍整体流程&#xff0c;遇到问题优先看“遇到问题章节”&#xff01; 一、安装anaconda 1.下载anaconda安装包 &#xff08;1&#xff09;可以选择在官网…

linux i2c-tools使用总结

1,安装iic-tools sudo apt install i2c-tools -y 2,查看有几条iic总线 [root@sino-platform:/root]# ls /dev/i2c- i2c-0 i2c-1 i2c-2 i2c-3 3,查看i2c命令 [root@sino-platform:/root]# i2c i2cdetect i2cdump i2cget i2cset 4,iic-help命令 [root@sino-platform…

postcss安装和使用(详细)

1,安装postcss&#xff1a; 在此之前需要安装有node.js 第一步 命令&#xff1a;cnpm install postcss-cli -g 第二步 命令&#xff1a;cnpm install postcss –g 推荐内容 2,下载autoprefixer插件&#xff0c;并创建postcss.config.js文件并写入配置代码 autoprefixer插件…

信息素养和社会责任

1.信息素养&#xff1a; 信息素养是一种了解、收集、评估、和利用信息的知识结构能力。 信息素养的四个要素&#xff1a;信息意识&#xff0c;信息知识&#xff0c;信息能力&#xff0c;信息道德 信息意识是先导&#xff08;前提&#xff09;&#xff0c;是对关键信息具有持…

大学教材《C语言程序设计》(浙大版)课后习题解析 | 第七、八章

概述 本文主要提供《C语言程序设计》(浙大版) 第七、八章的课后习题解析&#xff0c;以方便同学们完成题目后作为参考对照。后续将更新第九、十章节的课后习题解析&#xff0c;如想了解更多&#xff0c;请持续关注该专栏。 专栏直达链接&#xff1a;《C语言程序设计》(浙大版)…

【OceanBase实战之路】第3篇:多租户架构实现资源隔离

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 一、什么是OceanBase的多租户二、兼容模式2.1 MySQL 模式2.2 Oracle 模式三、租户介绍3.1 系统租户3.2 用户租户3.3 Meta 租…

STLExporter 是用于将 Three.js 场景中的几何体数据导出为 STL 格式的类。

demo案例 STLExporter 是用于将 Three.js 场景中的几何体数据导出为 STL 格式的类。下面是关于 STLExporter 的入参、出参、方法和属性的讲解&#xff1a; 入参 (Parameters): scene: THREE.Scene 类型的参数&#xff0c;表示要导出为 STL 格式的 Three.js 场景对象。 出参…

Python API(happybase)操作Hbase案例

一、Windows下安装Python库&#xff1a;happybase pip install happybase -i https://pypi.tuna.tsinghua.edu.cn/simple 二、 开启HBase的Thrift服务 想要使用Python API连接HBase&#xff0c;需要开启HBase的Thrift服务。所以&#xff0c;在Linux服务器上&#xff0c;执行如…

2024/3/31 蜂鸣器(1)

蜂鸣器分为有源蜂鸣器和无源蜂鸣器。有源内部自带振荡源&#xff0c;接上直流电压即可发声。无源则需要控制器提供振荡脉冲才可发声&#xff0c;调整提供振荡脉冲频率可以发出不同频率的声音。&#xff08;好想用stm32做个电子琴&#xff09; 驱动方式&#xff08;由于蜂鸣器所…

基于SpringBoot+Vue人口老龄化社区服务与管理平台(源码+部署说明+演示视频+源码介绍+lw)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

企微获客助手到底有哪些价值?

获客助手作为企业微信官方提供的获客工具&#xff0c;在私域布局中确实展现了其强大的引流效率和便利性。这一工具通过简化传统引流过程中的复杂步骤&#xff0c;使得企业能够更高效地吸引和转化潜在客户。此外&#xff0c;获客助手还能实现不同渠道的无缝链接&#xff0c;进一…

【研发日记】Matlab/Simulink开箱报告(十一)——Requirements Toolbox

目录 前言 Requirements Toolbox 编写需求 需求联接设计 需求跟踪开发进度 追溯性矩阵 分析和应用 总结 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;六&#xff09;——S-Fuction模块&#xff08;TLC&#xff09;》 见《开箱报告&#x…

Kafka开发实录

前言 最近我总是在做大胆的事情&#xff0c;莫不是少年也需要冲冲冲&#xff0c;明明我不是这样的人啊&#xff0c;难不成这就是命运&#xff0c;来自命运石之门的选择&#xff01;废话不多说&#xff0c;本次是Kafka的实战篇&#xff0c;为什么这篇这么快呢&#xff1f;看了开…