Linux内核分析:VFS和文件系统

今天学习的内容是,Linux文件系统中的VFS

写在前面

本来这篇应该全部都是VFS的,但是很遗憾,看完后发现只有一部分是VFS,而后面的大多是一些分析文件系统的源码,所以这篇只是包含了一部分VFS,但实际上大多还是文件系统中的知识

下载链接

链接: https://pan.baidu.com/s/1hRTh7rSesikisgRUO2GBpA?pwd=utgp 提取码: utgp

思维导图

在这里插入图片描述

下面是我在阅读中有一些比较困惑的问题,在这里总结出来:

一些问题

使用slab进行分配的优势和意义

使用slab分配器进行内存分配的优势和意义主要体现在以下几个方面:

一、优势
提高内存分配效率:
slab分配器以字节为单位进行内存分配,相较于传统的以页(通常是4KB)为单位的伙伴系统(Buddy System),它能够更精细地管理内存,减少内存浪费。
slab分配器通过维护一个对象缓存池,可以快速分配和回收相同类型的对象,避免了频繁调用伙伴系统带来的开销,提高了内存分配的效率。
减少内存碎片:
slab分配器将内存页划分为多个固定大小的内存块(slab对象),这些对象在分配和回收时都保持相同的大小,从而减少了内存碎片的产生。
内存碎片的减少有助于提高内存利用率,降低内存管理的复杂性。
支持硬件缓存对齐和着色:
slab分配器支持硬件缓存对齐,可以确保对象在内存中的位置与硬件缓存行对齐,从而加速内存访问速度。
同时,slab分配器还通过着色技术(Coloring)来优化缓存使用,使不同slab中的对象能够均匀地使用CPU缓存行,减少缓存冲突,提高缓存利用率。
支持快速初始化和回收:
当创建一个新的slab时,slab分配器会预先初始化多个对象并保存在缓存中。当需要分配对象时,直接从缓存中获取已初始化的对象,避免了重复初始化的开销。
对象回收时,slab分配器将其重新放入缓存中,保持其初始化状态,以便快速再次分配。
灵活的缓存策略:
slab分配器为每个类型的对象维护一个独立的缓存池,可以根据需要动态调整缓存的大小和数量。
这种灵活的缓存策略有助于更好地适应系统的内存使用情况和性能需求。
二、意义
优化内核性能:
slab分配器通过提高内存分配效率、减少内存碎片和优化缓存使用等方式,优化了Linux内核的性能。
这使得内核能够更高效地处理系统请求、提高响应速度并降低延迟。
支持高效的系统开发:
slab分配器为内核开发者提供了一种高效、灵活的内存管理机制,使得开发者可以更加专注于系统功能的实现而不是内存管理的细节。
这降低了系统开发的复杂性和难度,提高了开发效率。
提升系统稳定性和可靠性:
通过减少内存碎片和优化缓存使用等方式,slab分配器有助于提升系统的稳定性和可靠性。
这使得系统能够更好地应对各种复杂和多变的使用场景,减少因内存问题导致的系统崩溃和故障。
综上所述,使用slab分配器进行内存分配在Linux系统中具有显著的优势和意义。它不仅提高了内存分配的效率和性能,还优化了缓存使用、减少了内存碎片并提升了系统的稳定性和可靠性。这些优势对于提高Linux系统的整体性能和用户体验具有重要意义。

如何理解这段话:Linux 将新的文件系统通过一个称为“挂装”或“挂上”的操作将其挂装到某个目录上,从而让不同的文件系统结合成为一个整体。Linux 操作系统的一个重要特点是它支持许多不同类型的文件系统。

这段话描述了Linux操作系统中文件系统的多样性和它们如何被整合到一个统一的文件系统中。让我们一步步解析这段话:

文件系统的多样性
Linux操作系统支持多种不同类型的文件系统,这是它的一个重要特性。文件系统是操作系统用于在存储设备(如硬盘、SSD、USB驱动器、网络共享等)上组织、存储和检索文件的方式。不同的文件系统有不同的设计目标、性能和特性,例如,有些文件系统(如NTFS)专为Windows系统设计,而Linux则支持自己的一系列文件系统(如ext4、XFS、Btrfs等),同时也能够通过各种方式(如挂载NTFS分区)来访问其他操作系统的文件系统。

挂装(Mount)操作
“挂装”或“挂上”是一个术语,用于描述在Linux系统中将一个新的文件系统(可能位于物理设备、分区、网络共享或其他类型的存储介质上)连接到系统中的一个目录(称为挂装点)上的过程。这个操作使得文件系统的内容对操作系统和用户可见,并且可以通过文件系统层次结构中的挂装点来访问。

文件系统的整合
通过挂装操作,Linux能够将多个不同的文件系统整合到一个统一的文件系统中。这意味着,尽管这些文件系统可能位于不同的物理设备上,使用不同的格式,但用户可以通过统一的接口(即文件系统的层次结构)来访问它们。这种整合为用户提供了极大的灵活性和便利性,因为用户不需要关心文件具体存储在哪个物理设备上,只需要知道它们的逻辑位置即可。

总结
综上所述,这段话强调了Linux操作系统支持多种文件系统的能力,以及通过挂装操作将这些不同的文件系统整合到一个统一的文件系统中的方法。这种设计不仅提高了系统的灵活性和可扩展性,还为用户提供了更加便捷和高效的文件访问方式。

当然可以,我会用一个简单的例子来解释Linux中文件系统的挂装(Mount)操作。

假设你有一台Linux电脑,这台电脑有一个内置的硬盘,硬盘上安装了Linux操作系统。这个硬盘被分成了几个分区,比如一个分区用于存储Linux的根文件系统(/),另一个分区用于存储用户数据(比如/home),还有一个分区是空的或者格式化为另一种文件系统(比如NTFS,这是Windows常用的文件系统)。

现在,你有一个外部USB驱动器,它上面有一个NTFS格式的分区,里面存储了一些文件,这些文件是你从另一台Windows电脑上复制过来的。

为了在Linux上访问这些文件,你需要将USB驱动器上的NTFS分区挂装到Linux的文件系统树中的某个目录上。假设你决定将它挂装到/mnt/usb这个目录上(如果这个目录不存在,你需要先创建它)。

在Linux终端中,你可以使用mount命令来完成这个操作。命令可能看起来像这样:

bash
mount /dev/sdb1 /mnt/usb
这里的/dev/sdb1是USB驱动器上NTFS分区的设备文件(注意:/dev/sdb1是一个示例,实际设备文件可能因你的系统和USB驱动器而有所不同)。/mnt/usb是你想要将分区挂装到的目录。

执行这个命令后,USB驱动器上的NTFS分区就被挂装到了/mnt/usb目录上。现在,你可以像访问Linux中其他任何目录一样,通过cd /mnt/usb命令进入这个目录,并使用ls、cat、cp等命令来查看、读取、写入或复制其中的文件了。

这就是Linux中文件系统的挂装操作的一个简单例子。通过这种方式,Linux能够将多个不同的物理设备、分区或文件系统整合到一个统一的文件系统中,使得用户可以方便地访问和管理它们。

所以你的意思是说,Linux内部的文件系统比如说是ext2,而现在插入了一个u盘,这个u盘内部的文件系统可能不是ext2?而Linux就拥有能把这个文件系统纳入自己管理的一种方式,然后能让用户去访问到这个系统中的内容

完全正确!您的理解非常到位。

Linux内部(或者说,Linux所安装的硬盘上)的文件系统类型通常是Linux原生支持的文件系统之一,比如ext2、ext3、ext4、Btrfs、XFS等。这些文件系统都是为Linux设计的,具有高效、稳定等特性。

然而,当您插入一个U盘或外接硬盘时,这些存储设备上的文件系统可能与Linux内部的文件系统不同。例如,U盘可能格式化为FAT32、NTFS或exFAT等文件系统,这些都是为了跨平台兼容性而设计的文件系统,不仅Linux可以使用,Windows和macOS等其他操作系统也可以读取和写入。

Linux通过其强大的内核和文件系统模块,能够识别并挂载(Mount)这些不同类型的文件系统。挂载操作允许Linux将外部存储设备上的文件系统“附加”到Linux的文件系统树中的某个目录上,从而让用户能够像访问本地文件一样访问这些外部设备上的文件。

一旦挂载完成,用户就可以使用标准的Linux命令(如ls、cd、cp、mv等)来浏览、复制、移动或删除这些外部设备上的文件了。这种机制极大地提高了Linux的灵活性和兼容性,使得Linux用户能够轻松地使用各种不同类型的存储设备和文件系统。

和虚拟文件系统有什么关系

在探讨这个问题时,我们首先需要明确几个关键概念:虚拟文件系统(VFS, Virtual File System)、文件系统挂载,以及它们在操作系统中的作用和相互关系。

虚拟文件系统(VFS)
虚拟文件系统是Linux内核中的一个抽象层,它提供了一个统一的接口来访问不同的文件系统。VFS隐藏了不同文件系统之间的具体实现差异,使得用户和程序可以通过统一的接口来访问存储在各种介质上的数据,而无需关心数据的实际存储位置和格式。

VFS的主要作用包括:

提供统一的接口:无论底层使用何种文件系统(如ext4、NTFS、FAT32等),用户和程序都可以通过VFS提供的接口来访问文件。
支持多种文件系统:VFS能够同时支持多种文件系统,这使得Linux系统能够轻松地与其他操作系统进行文件交换。
缓存和缓冲:VFS还提供缓存和缓冲机制,以优化对文件的访问速度,减少对物理设备的读写次数。
文件系统挂载
文件系统挂载是指将存储设备(如硬盘、U盘、网络文件系统等)上的文件系统连接到Linux的文件系统树(或称为目录树)中的过程。通过挂载操作,存储设备上的文件系统被赋予了一个挂载点(即目录树中的一个目录),用户可以通过这个挂载点来访问存储设备上的文件。

挂载操作的主要步骤包括:

识别设备:当存储设备插入到Linux系统时,系统会识别并为其分配一个设备文件(如/dev/sdb1)。
创建挂载点:在文件系统树中选择或创建一个目录作为挂载点。
挂载文件系统:使用mount命令将存储设备上的文件系统挂载到指定的挂载点上。
虚拟文件系统与文件系统挂载的关系
虚拟文件系统(VFS)和文件系统挂载在Linux系统中是紧密相关的。

VFS作为抽象层:VFS提供了一个抽象层,使得挂载操作能够在不同的文件系统之间进行。无论是挂载ext4、NTFS还是其他类型的文件系统,VFS都能够提供统一的接口来访问这些文件系统。
挂载操作是VFS的具体实现:挂载操作是VFS在Linux系统中的具体实现方式之一。通过挂载操作,存储设备上的文件系统被整合到VFS中,成为Linux文件系统树的一部分。
共同支持数据访问:VFS和挂载操作共同支持了Linux系统对数据的访问。用户可以通过VFS提供的接口和挂载操作来访问存储在各种介质上的数据,而无需关心数据的实际存储位置和格式。
综上所述,虚拟文件系统(VFS)为Linux系统提供了一个统一的接口来访问不同的文件系统,而文件系统挂载则是将存储设备上的文件系统连接到VFS中的具体实现方式。它们共同支持了Linux系统对数据的灵活访问和管理。

对于虚拟文件系统的理解

我可以理解为是,Linux操作系统可以去识别多种文件系统,然后去获取其中的资源,但是如果单纯的去直接访问会带来较高的访问成本,因为不同的文件系统,它的访问方式不一样,所以Linux在上层封装了一个统一的接口层,在访问这些文件系统的时候,只需要用统一的方案来访问即可,而具体内部是怎么访问的不是上层关心的内容

元数据和数据

在文件系统中,元数据(Metadata)和数据(Data)是两个关键但不同的概念,它们共同构成了文件的完整表示。以ext4文件系统为例,这种关系在文件的存储和管理中尤为重要。以下是元数据和数据的详细区别:

一、定义与作用
元数据:

定义:元数据是关于数据的数据,它提供了关于文件的信息,但不包括文件名本身的内容。元数据描述了文件的属性,如大小、创建时间、修改时间、权限、所有者等。
作用:元数据使得操作系统能够有效地管理和访问文件,通过元数据,系统可以快速找到文件的存储位置、了解文件的权限等关键信息。
数据:

定义:数据是文件的实际内容,即用户创建或修改的文件信息,如文本、图片、视频等。
作用:数据是文件存在的核心价值,它包含了用户需要存储和传递的信息。
二、在文件系统中的存储
在ext4文件系统中,文件被分为元数据和数据进行存储:

元数据:通常存储在inode(索引节点)中。inode是文件系统的核心数据结构,它包含了文件的全部元数据,但不包含文件名。文件名是存储在目录的目录项(dentry)中的,目录项将文件名与inode编号关联起来。
数据:存储在数据块(Data Blocks)中。数据块是文件系统中用于存储文件内容的物理区域。当文件被创建或修改时,其数据会被写入到相应的数据块中。
三、操作与日志管理
在ext4等日志文件系统中,元数据和数据的操作都被记录在日志(Journal)中,但它们是分开管理的:

元数据日志:记录了对文件元数据的所有更改操作,如修改文件权限、所有者等。这些操作在写入磁盘之前,会先被记录到日志中,以确保在系统崩溃或突然断电时,元数据的一致性和完整性能够得到恢复。
数据日志:虽然数据本身不直接记录在日志中(因为数据量大,记录所有数据的更改会消耗大量资源),但数据块的分配和释放等关键操作会被记录在日志中。这样,在系统恢复时,可以根据日志中的信息来重建文件的数据结构。
四、性能与安全性的平衡
日志模式在提供数据安全性方面非常有效,因为它确保了即使在系统崩溃的情况下,文件系统的状态也能保持一致。然而,这种模式也可能对性能产生一定影响,因为写入操作需要等待日志的落盘才能继续。因此,在配置文件系统时,需要根据具体的应用场景和需求来平衡性能和安全性的要求。

综上所述,元数据和数据在文件系统中扮演着不同的角色,它们共同构成了文件的完整表示。了解它们之间的区别和关系对于深入理解文件系统的工作原理和优化文件系统的性能具有重要意义。

VFS

Linux内核

内存管理

  • 使用虚拟内存进行管理,基本单位是内存页

  • 借助slab分配器进行更小单元的分配,并提供使用情况等管理数据供上层进行管理

进程管理

  • 基于时间片和状态等进行管理,这个比较简单

文件系统

  • 将独立的文件系统组合成一个层次化的树形结构

    • Linux提供了不同文件系统转换的问题,比如插入一个u盘后把u盘内部的文件系统转换能访问的
  • 虚拟文件系统

    • 概念

      • 为了解决不同的文件系统访问接口不同,所以抽象出一个统一的接口,这个就是VFS
    • 分类

      • 逻辑文件系统

        • Linux所支持的文件系统,如ext2
      • 设备驱动程序

        • 为每一种硬件控制器所编写的设备驱动程序模块
    • 效果

      • 用户和进程不需要知道文件所在的文件系统类型,使用 Ext2 文件系统中的文件一样使用它们

设备驱动程序

  • 设备驱动程序运行在高特权级的处理器环境中,直接对硬件进行操作,任何错误都可能导致操作系统的崩溃

网络管理

  • 提供了对各种网络标准的存取和各种网络硬件的支持

Linux shell

概念

  • 系统的用户界面,提供了用户和内核进行交互操作的一种接口

    • 命令解释器,它解释由用户输入的命令并且把它们送到内核

文件系统

概念

  • 安装点

    • 对于文件系统来说,每一个文件都是/为根目录下的一个叶子,当新增一个设备就需要挂载到某个目录才能访问,这个目录就是安装点
  • 文件

    • 文件就是一个有序字节串,字节串中第一个字节就是文件的头,最后一个字节就是文件的尾
  • 目录项

    • 内核中的数据结构,缓存在内存
  • 目录

    • 目录是文件,持久化在磁盘,下次再次读到相同的目录时,只需从内存读就可以,大大提高了文件系统的效率
  • 索引节点

    • 文件属性的结构就是索引节点

文件的I/O操作

分类

  • 缓存I/O

    • 读操作

      • 已经缓存了,那就直接从缓存中返回

      • 否则从磁盘中读取,然后缓存在操作系统的缓存中

    • 写操作

      • 操作系统会先将数据从用户空间复制到内核空间的缓存中。这时对用户程序来说,写操作就已经完成

      • 至于什么时候再写到磁盘中由操作系统决定,除非显式地调用了sync同步命令

  • 直接IO

    • 应用程序直接访问磁盘数据,而不经过内核缓冲区,从而减少了在内核缓存和用户程序之间数据复制

write_begin(做日志相关的工作)

  • Journal(日志)模式

    • 在将数据写入文件系统前,必须等待元数据和数据的日志已经落盘才能发挥作用
  • order模式

    • 不记录数据的日志,只记录元数据的日志,但是在写元数据的日志前,必须先确保数据已经落盘
  • writeback

    • 不记录数据的日志,仅记录元数据的日志,并且不保证数据比元数据先落盘

源码分析

  • 初始化工作

    • 对于每一页,先调用address_space的write_begin做一些准备
  • 从用户拷贝到内核

    • 调用iov_iter_copy_from_user_atomic,将写入的内容从用户态拷贝到内核态的页中
  • 写操作

    • 调用address_space的write_end完成写操作
  • 判断脏页

    • 调用balance_dirty_pages_ratelimited,看脏页是否太多,需要写回硬盘

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 21:36:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 21:36:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 21:36:02       45 阅读
  4. Python语言-面向对象

    2024-07-15 21:36:02       55 阅读

热门阅读

  1. HarmonyOS赋能套件参考地址

    2024-07-15 21:36:02       14 阅读
  2. C++ 入门第12:模板(Template)

    2024-07-15 21:36:02       20 阅读
  3. 渗透环境安装篇之安装XSS漏洞靶场xss-labs

    2024-07-15 21:36:02       15 阅读
  4. Codeforces Round 957 (Div. 3)

    2024-07-15 21:36:02       19 阅读
  5. Qt中QTimer类使用简介

    2024-07-15 21:36:02       16 阅读
  6. 数仓实践:数据仓库建设公共规范指南

    2024-07-15 21:36:02       17 阅读