理解Linux文件系统

一、引言

磁盘的组成与分区

在Linux中,磁盘是存储数据的重要场所。要了解文件系统,我们首先需要了解磁盘的物理结构。磁盘由多个盘片叠加而成,每个盘片都有两个面,每个面都被划分为多个同心圆的磁道。而磁道上又被划分为多个扇区,每个扇区是磁盘的最小存储单位,通常存储512个字节到4K不等的数据。

在这里插入图片描述

我们都知道磁盘分区完毕后还需要进行格式化,之后操作系统才能够使用这个文件系统。 为什么需要进行“格式化”呢?这是因为每种操作系统所设置的文件属性/权限并不相同, 为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的“文件系统格式(filesystem)”。

传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如我们常听到的LVM与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统(例如LVM),也能够将多个分区合成一个文件系统(LVM, RAID)! 所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区。


二、Linux文件系统概述

1、文件系统的结构

在这里插入图片描述

该图表示了一个计算机硬盘分区结构的简化示意图,展示了硬盘从高级到低级的组织方式。第一行是分区,第二行是分组。以下是对该图要表示内容的详细分析:

  1. 磁盘(Disk):

    • 这是硬盘的顶层结构,代表了整个物理存储介质。
  2. 分区(Partitions):

    • 磁盘被划分为多个分区,例如“Partition 0”、“Partition 1”和“Partition 2”。
    • 分区是硬盘上逻辑上独立的存储区域,可以用于安装不同的操作系统、存储不同类型的数据等。
  3. 文件系统(File system):

    • 分区上建立了文件系统,这是操作系统用于组织和存储数据的一种方式。
    • 文件系统决定了如何在分区上创建、访问和管理文件和目录。
    • 每个分区可以有不同的文件系统。
  4. 块组(Block Groups):

    • 在文件系统内部,数据被进一步划分为块组(如“Block Group 0”)。
    • 块组是文件系统的逻辑单元,用于存储文件系统元数据(如inode表、位图等)和数据块。
    • 在该图中,标出了“Block Group 0-N”,通常一个文件系统会包含多个块组。
  5. 启动块(Boot Block):

    • 在某些文件系统(如Ext2/Ext3/Ext4)中,会有一个特殊的启动块,用于存储引导加载程序(bootloader)的代码。
    • 当计算机启动时,会从这个启动块读取并执行引导加载程序。
  6. 块组内部结构:

    • 每个块组包含多个子组件:

      • 超级块(Super Block):超级块位于文件系统的开头,用来描述整个文件系统的结构和状态。它包含了文件系统的各种重要信息,比如文件系统的大小、每个块的大小、inode表的大小、文件系统的布局等等。系统会对其进行备份,系统会将多个超级块内容保存到硬盘中的不同区域。

      • Inode表(Inode table):inode 是文件系统中的关键结构,它保存了文件的元数据,如文件名、权限、时间戳、数据块位置等。Inode 表就是存储所有inode的地方。

      • 数据块(Data blocks):文件系统中实际存储文件数据的地方,是文件系统上最小的可寻址单元。文件数据会被分割成多个块,存储在磁盘的不同位置。数据块的大小通常是固定的,例如4KB或8KB。

      • 位图(BitMap):

        通常是两种位图:块位图和inode位图。块位图记录了哪些数据块正在使用,哪些空闲;inode位图则记录了哪些inode正在使用,哪些空闲。下面两个位图是文件系统为了管理文件,而设置的管理字段。不属于某个文件。

        • inode位图(inode bitmap):记录哪些inode正在被使用,哪些空闲。
        • block位图(bock bitmap):记录了哪些数据块正在使用,哪些空闲。
        • 当删除一个文件时,文件系统并不会立即删除该文件在磁盘上存储的inode内容和数据块内容,而是会在inode位图和块位图中标记该文件所使用的inode和数据块(block)为空闲状态。这意味着该inode现在可以被重新分配给新的文件或目录。。直到新的inode和block将其覆盖。
      • 块组描述符表(Block Group Descriptor Table):

        管理所在的块组,这张表记录了每个块组的详细信息,如块组中的块数量、空闲块数量、inode数量等。group descriptor table管理整个分组,group descriptor table坏掉,整个分组就挂了。

    • 这些组件使得文件系统能够有效地追踪文件元数据和数据块的使用情况,并实现文件的有效读写操作。

本图表示了简洁计算机硬盘分区结构的组织方式,从磁盘到分区,再到文件系统和块组,最后到数据块和文件系统元数据的各个组成部分。这种结构使得数据在硬盘上能够被高效、有序地存储和访问。后文会更详细描述其中关键内容。

2、文件系统目录树的逻辑结构

Linux文件系统的目录树结构是一个倒置的树状结构,以根目录(/)为起点,向下展开形成多个子目录和文件。每个子目录都可以包含其他子目录或文件,形成一个庞大的文件系统结构。在目录树中,每个目录都有一个唯一的路径名,用于标识其在系统中的位置。通过路径名,用户可以轻松地访问和管理系统中的文件和目录。同时,Linux文件系统还支持目录的链接和别名功能,使得文件和目录的访问更加灵活和方便。


二、文件系统的特性

文件系统是操作系统管理文件数据的核心部分。在Linux系统中,每个文件不仅包含实际的内容数据,还包含一系列的属性信息,如文件的权限(rwx)、拥有者、群组以及时间参数等。这些属性和内容数据在文件系统中被分开存放,以实现更高效的管理。

即:Linux磁盘文件特性:文件=内容+属性。两者分开存储。

接下来我们继续探讨此图:

在这里插入图片描述

具体来说,文件的权限和属性信息被存储在inode(索引节点)中。每个文件或目录在文件系统中都有一个唯一的inode与之对应。inode不仅包含文件的元数据(如权限、拥有者、群组等),还包含指向文件实际内容数据所在位置的指针。

而文件的实际内容数据则存储在data block(数据块)中。当文件被创建或修改时,文件系统会根据需要分配相应的data block来存储文件的内容。由于data block的大小通常是固定的,因此可能存在空间利用率不高的情况,但文件系统通常会采用各种策略来优化这种空间使用。

除了inode和data block外,文件系统还有一个重要的组成部分是super block(超级区块)。super block存储了整个文件系统的全局信息,如inode和data block的总量、使用量、剩余量等。这些信息对于文件系统的管理和维护至关重要。

简单来说,文件系统通过inode、data block和super block等组件来管理文件的数据和属性信息。这种设计使得操作系统能够高效地访问和管理文件,同时提供了丰富的文件属性和权限控制功能。

1、super block:文件系统的超级块

文件系统的超级块(Super Block)是Linux文件系统中一个非常重要的概念,它用于存储文件系统的元数据信息。具体来说,超级块位于文件系统的开头,用来描述整个文件系统的结构和状态。它包含了文件系统的各种重要信息,比如文件系统的大小、每个块的大小、inode表的大小、文件系统的布局等等。

super block 是记录整个文件系统相关信息的地方, 没有 super block ,就没有这个文件系统了。

这些信息对于操作系统来说非常关键,因为操作系统需要依靠超级块来识别文件系统的类型、结构和状态,从而正确地读取和写入数据。在Linux系统中,超级块是由文件系统的驱动程序在文件系统挂载时从磁盘读取的。当一个文件系统挂载到某个挂载点时,操作系统会读取文件系统的超级块信息,并将其加载到内存中。这样,操作系统就可以根据超级块的信息来访问文件系统的数据、索引和目录结构,从而进行文件的读取、写入和管理。

每个分组中除了 super block,其他的内容均不一样。但是super block不是每个组都有。一般的block group中没有super block。

为了提高超级块的安全性,Linux操作系统还采用了备份超级块的设计。它会在多个block group中挑选几个block group写上super block。它会将多个超级块内容保存到不同区域。当其中一个超级块出现问题时,操作系统会自动采用另外一个超级块。这种安全机制在很大程度上提高了文件系统的稳定性和可靠性。

此时我们就能理解操作系统如果管理多个文件系统?

在操作系统开机时,要知道几个分区,几个文件系统。操作系统将每个分区的super block中的属性加载到内存里,构成多个结构体super block对象填充文件的属性。将所有的super block对象用链表管理起来,所有操作系统对文件系统的管理变成了对链表的增删改查。

具体来说,操作系统管理多个文件系统时,需要知道每个文件系统的位置和属性,并将这些信息加载到内存中以便快速访问:

  1. 文件系统挂载
    在操作系统启动后,或者用户手动挂载文件系统时,操作系统会读取每个文件系统的超级块(super block)。超级块包含了文件系统的类型、大小、块大小、inode数量等关键信息。
  2. 内存中的super block结构
    操作系统会将读取到的每个文件系统的super block信息加载到内存中,并创建一个与磁盘上super block相对应的内存数据结构。这个数据结构通常被称为“挂载点”(mount point)或“文件系统描述符”(filesystem descriptor)。
  3. 链表管理
    为了高效地管理这些文件系统描述符,操作系统通常使用链表(或其他数据结构,如树)来组织它们。这样,操作系统就可以通过遍历链表来查找、访问或修改任何挂载的文件系统。
  4. 访问文件系统
    当用户或程序尝试访问一个文件或目录时,操作系统会首先根据文件或目录的路径确定它属于哪个文件系统(即哪个挂载点)。然后,操作系统会使用与该文件系统对应的内存中的superblock结构和相关数据结构来找到文件的inode,进而访问文件的内容。
  5. 动态更新
    如果文件系统被卸载(unmount)或发生其他变化(如文件系统扩容、缩容等),操作系统会相应地更新内存中的文件系统描述符链表和相关数据结构。

通过这种方式,操作系统可以高效地管理多个文件系统,并提供对文件和目录的透明访问。用户或程序无需关心文件或目录具体位于哪个物理磁盘或分区上,只需要通过统一的路径和接口来访问它们即可。

一个被写入文件系统的分区,要被linux使用,必须要把这个具有文件系统的分区进行挂载。一个文件系统所对应的分区,必须挂载到目录当中。

2、inode:文件系统的索引节点

iode是文件系统中一个重要的数据结构,用于存储文件或目录的元数据。具体来说,inode保存了一个文件系统对象(如目录、文件、管道、软连接、socket、设备文件等)的元数据信息,如文件的字节数、文件拥有者的UserID、文件的GroupID、文件的读、写、执行权限、文件的时间戳、链接数以及文件数据block的位置等。但是Linux系统中,文件的属性不包含文件名。

inode的作用主要体现在操作系统按inode的编号对文件进行识别,这种编号在同一文件系统内是唯一的。当我们打开一个文件时,系统会先通过文件路径找到该文件所在的目录,然后根据文件名在目录中查找对应的目录项,最后获取目录项中存储的inode号。通过inode号,系统可以查找文件的元数据信息,并访问文件的内容。因此,文件路径、目录项和inode号是Linux文件系统中的三个重要概念,它们共同构成了文件系统的基本结构。

一个文件一个inode。inode编号在整个分区内唯一,不是在数据块内唯一。系统中,标志一个文件,不是用的文件名,而是inode编号。

系统中,又因为文件名不属于文件的属性,因此标志一个文件,使用的是inode。我们通常可以使用 ls -i来查询文件的inode:

在这里插入图片描述

至于inode如何与文件和目录关联,主要是通过目录项(directory entry)来实现的。目录项是一个数据结构,它包含了文件名和文件的inode号之间的映射关系。每个目录都是一个文件,它包含了多个目录项,每个目录项包含了一个文件名和一个inode号。当用户在文件系统中打开一个文件时,系统会根据文件名查找对应的目录项,获取该文件的inode号,再根据inode号获取到inode信息,从而访问文件的内容。

3、inode table

每个inode都是inode table中的一个条目,具有唯一的编号(即inode编号),用于标识和访问特定的文件或目录。因此,inode table可以被视为文件系统中所有文件和目录的元数据的索引或目录。

在文件系统中,每个文件或目录都与一个唯一的inode相关联,而inode中包含了指向该文件或目录的数据块(block)的指针。这些指针指向存储文件或目录实际数据的位置。因此,通过inode table中的inode,操作系统可以快速地找到并访问文件或目录的元数据和数据块。

4、block:文件系统的数据块

在文件系统中,数据块(block)是实际存储文件数据的单位。当文件内容较大时,数据会被分成多个数据块存储在存储设备上。这些数据块通常由多个扇区组成,并在格式化文件系统时选择块的大小。

在Linux系统中,如ext2文件系统,数据块是文件系统中存储数据的地方,分为三种类型:数据块、索引块和间接块。数据块用于存储文件的实际数据,索引块用于访问大文件,而间接块用于访问非常大的文件。

此外,数据块与inode(索引节点)密切相关。inode记录了文件或目录的元数据信息,包括文件的权限、所有者、文件大小、创建时间等。每个文件或目录都对应着一个唯一的inode,而inode中包含了指向文件数据块的指针,使得操作系统能够定位和访问文件的数据块。

总之,数据块是文件系统中实际存储文件数据的物理单位,而inode是文件或目录的元数据信息记录,两者共同构成了文件系统的基本结构。

5、块组描述符表(Block Group Descriptor Table)

块组描述符表(Block Group Descriptor Table,简称GDT)是Linux文件系统中用于存储每个块组(Block Group)元信息的表

在Linux文件系统中,整个分区被划分为若干个大小相同的块组,每个块组都由多个部分组成,包括超级块、块组描述符表、块位图、inode位图、inode表和数据块等。

块组描述符表由多个块组描述符组成,每个块组描述符存储了一个块组的描述信息。这些信息包括块组中inode表和数据块的位置,以及空闲的inode和数据块的数量等。通过这些信息,文件系统能够了解每个块组的使用情况,从而高效地管理磁盘空间。

当文件系统需要创建新的文件或目录时,它会根据块组描述符表的信息来找到空闲的inode和数据块进行分配。同样地,当文件或目录被删除时,文件系统也会根据这些信息来更新块组描述符表,将空闲的inode和数据块标记为可用状态。

6、小结

从上述内容,我们可以发现每个文件(不管是目录文件还是一般的文件)都会占用一个inode,且可以一句文件内容的大小来分配多个block给该文件使用。

我们如何理解目录文件的内容是什么呢?

目录的内容在记录文件名,一般文件才是实际记录数据内容的地方。当我们在 Linux 下的文件系统创建一个目录时,目录也是一个文件。因此目录也有自己的inode(inode编号等)+目录的内容。任何一个普通文件,一定在一个目录中。文件系统会分配一个inode与至少一块block 给该目录。其中,inode记录该目录的相关权限与属性,并可记录分配到的那块block号码; 而block则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据,准确来说是记录inode编号和文件名的对应关系。

当然,我们也需要理解文件系统是如何找到我们所需要的文件。

在Linux文件系统中,当你想要通过inode编号找到文件时,确实需要知道inode所属的块组(block group)。在大多数文件系统(如ext2、ext3、ext4)中,inode不是随机分布在磁盘上的,而是按照块组进行组织的。每个块组都包含了一定数量的inode和数据块。

为了确定一个inode所属的块组,文件系统使用了以下策略:

  1. 计算inode所属的块组号
    • 文件系统通常会在超级块(super block)中存储每个块组中的inode数量。
    • 你可以通过inode编号和每个块组中的inode数量来计算inode所属的块组号。具体计算方式取决于文件系统的具体实现,但通常是将inode编号除以每个块组中的inode数量,取商作为块组号。
  2. 定位块组描述符
    • 块组描述符表(Block Group Descriptor Table)位于文件系统的固定位置,并包含了每个块组的描述信息。
    • 一旦你知道了inode所属的块组号,你就可以通过块组描述符表找到对应的块组描述符。
  3. 读取inode
    • 块组描述符中包含了inode表(inode table)在磁盘上的位置信息。
    • 使用块组描述符中的信息,你可以定位到inode表,并从中找到具有指定inode编号的inode。
  4. 读取文件数据
    • inode中包含了指向文件数据块的指针。
    • 使用这些指针,你可以从数据块中读取文件的内容。

需要注意的是,这个过程对于用户空间的应用程序来说通常是不可见的。用户空间的应用程序通过系统调用(如openreadwrite等)与文件系统交互,而文件系统内核模块则负责处理这些系统调用,并执行上述的inode查找和数据读取过程。

同时我们可以更清晰的理解文件的创建、读取、删除操作

  • 当文件被创建时,文件系统会在inode位图中找到一个空闲的inode号,并在inode表中分配一个inode。然后,文件系统会在块位图中找到足够数量的空闲数据块来存储文件内容,并在inode中设置指向这些数据块的指针。
  • 当文件被读取时,文件系统会根据文件名在目录的inode中找到对应的文件名和inode号,然后读取inode以获取文件的数据块指针。接着,文件系统会按照指针顺序读取数据块并返回文件内容。
  • 当文件被删除时,文件系统会在inode位图中标记inode为空闲状态,并在块位图中标记文件所使用的数据块为空闲状态。这些空闲的inode和数据块可以被新文件或目录所使用。

三、文件权限和所有权:

在Linux中,文件和目录的权限和所有权是文件系统的核心安全特性之一。这些权限和所有权决定了哪些用户可以访问文件或目录,以及他们可以对这些文件或目录执行哪些操作。

1、文件权限

Linux文件权限定义了三种基本类型的访问权限:读(r)、写(w)和执行(x)。这些权限可以针对三种不同的用户类别进行设置:文件的所有者(user)、文件所属的用户组(group)和其他用户(others)。

  • 读(r):允许用户读取文件内容或列出目录内容。
  • 写(w):允许用户修改文件内容或向目录中添加/删除文件。
  • 执行(x):允许用户执行文件(如果它是一个程序或脚本),或者进入目录(cd命令)。

权限通常以字符(rwx)或数字(4、2、1)的形式表示。字符形式更直观,而数字形式则便于进行权限的算术运算。每个字符或数字对应一个权限位,组合起来就构成了文件的权限。

例如,权限字符串-rw-r--r-- 表示文件所有者有读写权限,而文件所属的用户组和其他用户只有读权限。对应的数字表示法为644(所有者 rw=4+2=6, 用户组 r=4, 其他用户 r=4)。

2、所有权

Linux文件系统中的每个文件和目录都有一个所有者(UID)和一个所属的用户组(GID)。这些值用于确定文件的访问权限。

  • UID(User ID):用户标识符,用于唯一标识系统中的用户。每个文件都有一个与之关联的所有者UID,用于确定文件所有者的权限。
  • GID(Group ID):组标识符,用于唯一标识系统中的用户组。每个文件都有一个与之关联的所属用户组GID,用于确定文件所属用户组的权限。

在这里插入图片描述

通过ls -l命令可以查看文件和目录的权限和所有权信息。输出中的第一个字段显示了文件的权限和所有权信息。

例如-rw-r--r-- 1 user group 1234 May 10 10:00 filename。其中,user是文件所有者的用户名,group是文件所属的用户组名,1234是文件大小(以字节为单位)。

3、权限设置

可以使用chmod命令来修改文件或目录的权限。例如,chmod u+x filename将给文件的所有者添加执行权限。同样地,可以使用chownchgrp命令来修改文件或目录的所有者和所属用户组。例如,chown newuser filename将把文件的所有者更改为newuser


四、inode与文件权限以及文件增删改查的联系

1、权限

有了inode和文件权限的概念,我们将他们联系起来。

首先,如果一个目录没有r,w,x表现是什么?

  • 可执行权限(x): 如果目录没有可执行权限, 则无法cd到目录中。
  • 可读权限(r): 如果目录没有可读权限, 则无法用ls等命令查看目录中的文件内容。
  • 可写权限(w): 如果目录没有可写权限,,则无法在目录中创建文件, 也无法在目录中删除文件。即对目录的inode属性无法写。

又因为文件全是是inode的一部分,当系统需要访问文件的权限时,它会首先通过文件名在目录的inode中找到对应的文件名和inode号,然后读取inode以获取文件的权限信息。这个过程是在文件系统内部自动完成的,用户通常不需要直接操作inode。

而且当使用chmod命令修改文件的权限时,文件系统会更新与该文件关联的inode中的权限字段。这样,下次系统访问该文件时就会读取到新的权限设置。

2、文件的增删查改

Linux系统中文件增删查改的基本过程和权限的影响。对一个文件的增删改查都与该文件所在的目录有关。

新建一个文件

  1. 分配inode:系统会在inode位图中查找一个未被使用的inode号,并标记为已使用。
  2. 填写inode属性:在inode table中,系统会根据文件类型(普通文件、目录等)和其他属性(如权限、所有者、大小等)来初始化inode。
  3. 分配数据块:对于普通文件,系统还会在数据块位图中查找并分配数据块来存储文件内容。
  4. 写入目录:系统将文件名和inode号之间的映射关系写入当前目录的目录中(即目录文件的内容)。这通常涉及到在目录文件中添加一个新的条目。

删除一个文件

  1. 查找inode:系统会根据文件名在当前目录的内容中进行字符串匹配,找到对应的inode号。
  2. 清理inode和数据块:系统会在inode位图和数据块位图中标记相关的inode和数据块为未使用,并释放它们以供将来使用。
  3. 移除目录条目:最后,系统会从目录文件中移除文件名和inode号之间的映射关系。

查找一个文件

当用户请求访问一个文件时(如使用cat命令读取文件内容),系统会逆向的递归般地得到根目录,然后从根目录开始,根据文件路径中的每个目录名和文件名,逐级查找对应的inode号,直到找到目标文件的inode号。然后,系统会根据inode号找到文件的数据块,并读取或写入数据。

这个过程是递归的,因为文件路径可能包含多个目录。在每个目录级别,系统都需要查找目录文件的内容以获取下一个目录或文件的inode号。这种查找方式通常被称为“路径解析”或“目录解析”。

文件修改

  1. 当修改文件的内容时,实际上是在修改与文件关联的inode中的数据块的内容。inode中的指针保持不变,但指向的数据块内容会发生变化。

  2. 如果修改导致文件大小增加并需要额外的数据块来存储新增的内容,系统会为文件分配新的数据块,并更新inode中的指针以反映这些更改。

权限与文件创建/删除/查询

  • 没有w权限

    • 如果用户在当前目录中没有写权限(w),那么他们无法在该目录中创建新文件或删除文件。这是因为创建新文件需要在目录中写入新的映射关系,而删除文件则需要从目录中移除旧的映射关系。
    • 具体来说,用文件名在当前目录的内容中做字符串匹配,保证我们找到了它的文件名对应的inode,根据inode确定在哪个分组里面,把它的位图清理。删完后把文件名和inode映射关系从目录中去掉即可。因此删文件也需要修改文件内容。即没有w权限不能删除不能创建文件。
  • 没有r权限

    • 如果用户没有目录的读权限(r),那么他们无法列出目录中的文件(如使用ls命令)。这是因为他们无法读取目录文件的内容,即文件名和inode号之间的映射关系。
    • 查找一个文件的过程中,在内核里,都要逆向的递归般地得到根目录,然后从根目录往下进行目录解析。如果对一个目录没有r权限,则无法读取目录中的文件,原因是我们就无法读取映射关系,不能读取文件的信息。如果目录没有r权限,则无法用ls等命令查看目录中的文件内容。

总之,Linux中的文件和目录操作涉及到inode、数据块、目录文件以及权限等多个方面。这些概念和机制共同构成了文件系统的基础,使得用户能够方便、高效地管理和使用文件。

  • 43
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌岩雀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值