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结构体之间的关系

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HAProxy + Vitess负载均衡

一、环境搭建 Vitess环境搭建: 具体vitess安装不再赘述,主要是需要启动3个vtgate(官方推荐vtgate和vtablet数量一致) 操作: 在vitess/examples/common/scripts目录中,修改vtgate-up.sh文件,…

【GitLab】Ubuntu 22.04 快速安装 GitLab

在 Ubuntu 22.04 上安装最新版本的 GitLab,可以按照以下步骤操作: 1. 更新系统: 在终端中执行以下命令以确保系统是最新的: sudo apt update sudo apt upgrade2. 安装依赖: 安装 GitLab 所需的依赖包: …

vue2.0脚手架搭建

vue起步 文档 https://v2.cn.vuejs.org/ {{}} 变量、表达式渲染v-html html模板,渲染htmlv-model 绑定值(双向绑定)v-if 判断v-bind:href"地址" 简写:绑定属性 简写:href:"&qu…

SQL109 纠错4(组合查询,order by..)

SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state MI UNION SELECT cust_name, cust_contact, cust_email FROM Customers WHERE cust_state IL ORDER BY cust_name;order by子句,必须位于最后一条select语句之后

Android vehicle车辆属性新增demo

目录 前言一、Vehicle模块1.1 简介1.2 Vehicle框架1.3 主要功能和特点1.4 重要服务CarService1.4.1 简介1.4.2 组成1.4.3 启动时序1.4.4 作用 二、车辆属性新增demo2.1 CarPropertyService2.1.1 简介2.1.2 架构2.1.3 车辆属性 API2.1.4 CarPropertyService 初始化流程 2.2 App …

上岸美团了!

Hello,大家好,最近春招正在如火如荼,给大家分享一份美团的面经,作者是一份某双非的硕(只如初见668),刚刚通过了美团的3轮面试,已经拿到offer,以下是他的一些分享。 一面&…

Rust编程(四)PackageCrateModule

这一部分的中文教程/文档都很混乱,翻译也五花八门,所以我建议直接看英文官方文档,对于一些名词不要进行翻译,翻译只会让事情更混乱,本篇从实战和实际需求出发,讲解几个名称的关系。 Module & Crate & Package & Workspace 英文中的意思: Cargo:货物 Crate:…

遥感数字图像处理的学习笔记

相关链接: 遥感数字图像处理实验教程(韦玉春)--部分实验问题回答 目录 1.什么是图像,什么是数字图像? 2.什么是遥感数字图像?模拟图像(照片)与遥感数字图像有什么区别? 3.什么是遥感数字图像…

java数组与集合框架(一) -- 数据结构,数组

数据结构 概述 为什么要讲数据结构? 任何一个有志于从事IT领域的人员来说,数据结构(Data Structure)是一门和计算机硬件与软件都密切相关的学科,它的研究重点是在计算机的程序设计领域中探讨如何在计算机中组织和存储…

【公示】2023年度青岛市级科技企业孵化器拟认定名单

根据《青岛市科技企业孵化器管理办法》(青科规〔2023〕1号)(以下简称《管理办法》)、《关于开展2023年度市级科技企业孵化器认定申报工作的通知》,经申报受理、区市推荐、形式审查、专家评审及现场核查等程序&#xff…

鸿蒙开发(七)-UIAbility启动模式

鸿蒙开发(七)-启动模式 根据代码中定义,UIAbility的启动模式有以下几种: "launchType": {"description": "Indicates the boot mode of ability.","type": "string","enum": ["standard",…

【数据结构与算法篇】动态顺序表及相关OJ算法题

【数据结构与算法篇】动态顺序表及相关OJ算法题 🥕个人主页:开敲🍉 🔥所属专栏:数据结构与算法🍅 目录 【数据结构与算法篇】动态顺序表及相关OJ算法题 1. 动态顺序表的实现 1.1 SeqList.h 头文件声明 1.…

【进程IO】详细讲解文件描述符fd

文章目录 前言什么叫文件描述符FILE与fd的关系 再次理解文件为什么要有文件的方法列表呢? 进程和struct file的关系再次理解open操作 前言 C语言的关于文件操作的各种函数实际上是对系统调用的封装。那么从进程的角度看,一个文件到底是如何被描述的呢&a…

【Java数据结构】关于栈的操作出栈,压栈,中缀表达式,后缀表达式,逆波兰表达式详解

🔥个人主页:努力学编程’ 🔥内容管理:java数据结构 上一篇文章我们讲过了java数据结构的链表,对于链表我们使用了它的一些基本操作,完成了扑克牌小游戏的操作,如果你感兴趣的话,点…

了解 LoadRunner 性能测试软件及其基础使用

目录 一、了解LoadRunner 1、什么是Loadrunner? 2、Loadrunner包括什么组件? (1)前台组件 (2)后台组件 二、LoadRunner三大组件 1、VuGen(虚拟用户脚本生成器) (…

Vue + .NetCore前后端分离,不一样的快速发开框架

摘要: 随着前端技术的快速发展,Vue.NetCore框架已成为前后端分离开发中的热门选择。本文将深入探讨Vue.NetCore前后端分离的快速开发框架,以及它如何助力开发人员提高效率、降低开发复杂度。文章将从基础功能、核心优势、适用范围、依赖环境等…

linux基础命令篇:Linux基础命令讲解——文件浏览(cat、less、head、tail和grep)

Linux基础命令讲解——文件浏览(cat、less、head、tail和grep) 本文详细介绍Linux中的cat、less、head、tail和grep命令,这些命令在日常工作中非常实用,以下是关于这些命令的详细介绍: 1. cat命令:用于查看…

JDK8的下载安装与环境变量配置教程

前言 官网下载:Java Archive Downloads - Java SE 8u211 and later 现在应该没人用32位的系统了吧,直接下载Windows x64 Installer jdk-8u391-windows-x64.exe 一、安装JDK 1. 打开jdk-8u391-windows-x64.exe 2. 直接下一步 3. 这个地方不要动他&…

鸿蒙OS开发实例:【瀑布流式图片浏览】

介绍 瀑布流式展示图片文字,在当前产品设计中已非常常见,本篇将介绍关于WaterFlow的图片浏览场景,顺便集成Video控件,以提高实践的趣味性 准备 请参照[官方指导],创建一个Demo工程,选择Stage模型熟读Har…

构建操作可靠的数据流系统

文章目录 前言数据流动遇到的困难先从简单开始可靠性延迟丢失 性能性能损失性能——分层重试 可扩展性总结 前言 在流式架构中,任何对非功能性需求的漏洞都可能导致严重后果。如果数据工程师没有将可伸缩性、可靠性和可操作性等非功能性需求作为首要考虑因素来构建…