[Linux]The Filesystem

The Filesystem

1 文件系统层次结构标准

在Linux或Unix-like系统中,文件系统层次结构标准(Filesystem Hierarchy Standard, FHS)为系统的目录结构提供了一套规范。执行ls -l /命令可以查看根目录下的子目录列表。以下是各个主要目录的简要介绍:

  • /:整个文件系统的根目录,所有其他目录和文件都位于此目录之下。
  • /bin:存放系统必需的二进制程序,包括基础命令如lscp等。
  • /boot:包含内核及启动引导加载器的文件。
  • /dev:设备文件,代表系统中的硬件设备。
  • /etc:核心系统配置文件所在目录,通常仅包含配置文件而非可执行文件。
  • /home:用户个人目录,存储用户的文档、文件和个人设置。
  • /lib:库文件,供/bin和/sbin中的二进制文件使用。
  • /media:用于挂载可移动媒体,如USB驱动器的挂载点。
  • /mnt:临时挂载文件系统的挂载点。
  • /opt:可选的应用软件包。
  • /proc:关于当前运行进程的信息。
  • /root:root用户的主目录。
  • /run:自上次启动以来关于运行系统的动态数据。
  • /sbin:系统必备的管理工具,通常只能由超级用户(root)执行。
  • /srv:由系统提供的特定站点数据。
  • /tmp:存储临时文件。
  • /usr:用于用户安装的软件和实用工具,并非传统意义上的用户文件(例如/home下的用户目录)。该目录下还有进一步的子目录,如/usr/bin/usr/local等。
  • /var:变量文件目录,用于系统日志、用户跟踪、缓存等随时间变化的数据。

2 文件系统类型

在计算机中,存在多种文件系统实现,每种都有其特定的应用场景和优势。文件系统的差异体现在速度、支持的存储容量以及数据组织方式上。为了使应用程序能够在不同类型的文件系统上运行,引入了虚拟文件系统(Virtual File System, VFS)抽象层,它作为应用与具体文件系统间的中介,确保应用可以无缝地操作各种文件系统。

日志文件系统

现代文件系统通常默认支持日志功能。日志文件系统通过记录即将进行的操作来预防突然断电等情况导致的数据损坏或文件系统不一致。在非日志文件系统中,突发断电可能导致文件损坏,并需要在下次启动时进行全面检查以修复问题,这可能耗时较长。而在日志文件系统中,所有操作先被记录到日志中,在操作完成后标记为完成,从而保持文件系统的完整性并减少重启时的检查时间。

常见桌面文件系统类型

  • ext4:Linux最新的原生文件系统,向后兼容ext2和ext3。支持最大1EB的磁盘卷和最大16TB的文件大小,是Linux的标准选择。
  • Btrfs:一种新的Linux文件系统,提供快照、增量备份等功能,性能有所提升,但稳定性尚待完善。
  • XFS:高性能的日志文件系统,适合用于大型文件如媒体服务器。
  • NTFS和FAT:Windows操作系统使用的文件系统。
  • **HFS+**:苹果Macintosh电脑所用的文件系统。

使用df -T命令可以查看当前系统中挂载的文件系统类型及其使用情况:

1
2
3
4
5
6
pete@icebox:~$ df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sda1 ext4 6461592 2402708 3707604 40% /
udev devtmpfs 501356 4 501352 1% /dev
tmpfs tmpfs 102544 1068 101476 2% /run
/dev/sda6 xfs 13752320 460112 13292208 4% /home

上述命令展示了每个文件系统的类型、块大小、已用空间、可用空间及挂载点等信息。

3 磁盘结构解析

硬盘可以通过分区被细分为多个块设备,例如/dev/sda1和/dev/sda2。其中,/dev/sda代表整个磁盘,而/dev/sda1表示该磁盘的第一个分区。分区有助于数据分离,并且可以根据需要创建特定文件系统的分区,而不是将整个磁盘格式化为单一类型的文件系统。

分区表

每个磁盘都有一个分区表,用于描述磁盘是如何分区的。它标明了各个分区的起始与结束位置、哪些分区是可引导的以及各分区所占的扇区等信息。常用的分区表类型有两种:MBR(主引导记录)和GPT(GUID分区表)。

分区

磁盘由多个分区组成,这些分区帮助我们组织数据。一个磁盘上可以有多个不重叠的分区。未分配给任何分区的空间被称为自由空间。分区的类型取决于分区表。分区既可以包含文件系统,也可以专门用于其他用途,如交换分区。

MBR与GPT

  • MBR:传统分区表,最多支持四个主分区。通过创建扩展分区(仅允许一个),可以在其内部添加逻辑分区,从而实现更多的分区。
  • GPT:作为新的标准逐渐取代MBR,支持更多的分区数量,每个分区拥有全局唯一的标识符(GUID)。主要用于UEFI引导模式下的磁盘分区。

文件系统结构

文件系统是一个有序的文件和目录集合。基本组成部分包括:

  • 引导块:位于文件系统的前几个扇区,包含操作系统启动所需的信息。
  • 超级块:紧跟引导块之后,包含了关于文件系统的重要信息,如inode表大小、逻辑块大小及文件系统的总大小。
  • inode表:可以看成是管理文件的数据库,每个文件或目录在inode表中都有唯一入口,包含文件的各种属性信息。
  • 数据块:实际存储文件和目录数据的部分。

以下是使用不同分区表的实际例子:

MBR分区表示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pete@icebox:~$ sudo parted -l

Model: Seagate (scsi)

Disk /dev/sda: 21.5GB

Sector size (logical/physical): 512B/512B

Partition Table: msdos


Number Start End Size Type File system Flags

1 1049kB 6860MB 6859MB primary ext4 boot

2 6861MB 21.5GB 14.6GB extended

5 6861MB 7380MB 519MB logical linux-swap(v1)

6 7381MB 21.5GB 14.1GB logical xfs

GPT分区表示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Model: Thumb Drive (scsi)

Disk /dev/sdb: 4041MB

Sector size (logical/physical): 512B/512B

Partition Table: gpt


Number Start End Size File system Name Flags

1 17.4kB 1000MB 1000MB first

2 1000MB 4040MB 3040MB second

上述命令展示了磁盘及其分区的具体情况,包括分区的起始位置、大小、类型、文件系统及标志等信息。

4 磁盘分区

分区工具选择

有多种工具可用于磁盘分区:

  • fdisk:基础命令行分区工具,不支持GPT。
  • parted:支持MBR和GPT的命令行工具。
  • gparted:parted的图形用户界面版本。
  • gdisk:仅支持GPT的fdisk版本。

使用parted对磁盘进行分区。假设连接USB设备后,设备名为/dev/sdb2

使用Parted进行分区

  1. 启动parted

    1
    $ sudo parted

    进入parted工具后,可以通过命令对设备进行分区操作。

  2. 选择设备

    在parted工具中,首先需要选择要操作的设备:

    1
    (parted) select /dev/sdb2
  3. 查看当前分区表

    使用print命令查看选定设备的现有分区情况:

    1
    (parted) print

    输出示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Model: Seagate (scsi)

    Disk /dev/sda: 21.5GB

    Sector size (logical/physical): 512B/512B

    Partition Table: msdos


    Number Start End Size Type File system Flags

    1 1049kB 6860MB 6859MB primary ext4 boot

    2 6861MB 21.5GB 14.6GB extended

    5 6861MB 7380MB 519MB logical linux-swap(v1)

    6 7381MB 21.5GB 14.1GB logical xfs

    此处列出了设备上的所有分区及其起始和结束位置。

  4. 创建新分区

    选择合适的起始和结束位置来创建新分区:

    1
    (parted) mkpart primary 123 4567

    需要指定分区类型(根据使用的分区表类型)。

  5. 调整分区大小

    如果空间不足,可以调整分区大小:

    1
    (parted) resize 2 1245 3456

    选择分区编号,并指定新的起始和结束位置。

5 创建文件系统

在完成磁盘分区后,下一步是创建文件系统。以下是创建文件系统的步骤:

使用mkfs命令创建文件系统

假设已对/dev/sdb2进行了分区,现在我们可以在此分区上创建一个ext4文件系统:

1
$ sudo mkfs -t ext4 /dev/sdb2

此命令使用mkfs(make filesystem)工具,并通过-t参数指定文件系统类型为ext4和目标设备路径。

重要提示:仅应在新分区的磁盘或重新分区的旧磁盘上创建文件系统。若在一个已有文件系统的分区上再次创建文件系统,可能会导致文件系统损坏。

6 挂载与卸载文件系统

在查看文件系统内容之前,必须先将其挂载到系统上。这需要设备位置、文件系统类型以及挂载点,其中挂载点是系统中的一个目录,用于将文件系统附加于此。

创建挂载点并挂载文件系统

首先创建挂载点,例如:

1
$ sudo mkdir /mydrive

然后使用mount命令挂载设备:

1
$ sudo mount -t ext4 /dev/sdb2 /mydrive

这里,-t参数指定文件系统类型,随后是设备位置和挂载点。

卸载文件系统

要从挂载点卸载设备,可以使用以下任一命令:

1
$ sudo umount /mydrive

或者

1
$ sudo umount /dev/sdb2

注意:内核会按照发现设备的顺序命名它们。如果设备名称在挂载后发生变化,可以使用设备的UUID(通用唯一标识符)来代替名称进行挂载。

查看和使用UUID

使用blkid命令查看系统中块设备的UUID:

1
$ sudo blkid

示例输出可能如下所示:

1
2
3
/dev/sda1: UUID="130b882f-7d79-436d-a096-1e594c92bb76" TYPE="ext4"
/dev/sda5: UUID="22c3d34b-467e-467c-b44d-f03803c2c526" TYPE="swap"
/dev/sda6: UUID="78d203a0-7c18-49bd-9e07-54f44cdb5726" TYPE="xfs"

通过UUID挂载设备的方法如下:

1
$ sudo mount UUID=130b882f-7d79-436d-a096-1e594c92bb76 /mydrive

通常情况下,无需通过UUID挂载设备,直接使用设备名更为简便。但若需在启动时自动挂载文件系统,如添加了第二块硬盘,则应使用UUID。

7 自动挂载文件系统:/etc/fstab

为了在系统启动时自动挂载文件系统,可以将其添加到/etc/fstab文件中。该文件是文件系统表的简称,包含了系统启动时需要挂载的文件系统的永久列表。

示例/etc/fstab内容如下:

1
2
3
UUID=130b882f-7d79-436d-a096-1e594c92bb76 /               ext4    relatime,errors=remount-ro 0       1
UUID=78d203a0-7c18-49bd-9e07-54f44cdb5726 /home xfs relatime 0 2
UUID=22c3d34b-467e-467c-b44d-f03803c2c526 none swap sw 0 0

每一行代表一个文件系统,字段含义分别为:

  • UUID:设备标识符。
  • 挂载点:文件系统挂载到的目录。
  • 文件系统类型:如ext4、xfs等。
  • 选项:其他挂载选项,详情可参阅相关手册页。
  • 转储标志:用于转储工具决定何时进行备份,默认设为0即可。
  • 文件系统检查顺序:由fsck使用,决定文件系统的检查顺序。值为0表示不检查。

添加新条目

要添加新的挂载条目,直接编辑/etc/fstab文件并按上述语法格式加入相应的信息。修改此文件时需谨慎,错误的更改可能会导致系统问题。

8 交换分区(Swap)的使用与管理

查看分区表。聚焦于其中特定的一行:

1
2
Number  Start   End    Size    Type       File system    Flags
5 6861MB 7380MB 519MB 逻辑分区 linux-swap(v1)

什么是交换分区?

交换分区(swap)用于为系统分配虚拟内存。当物理内存不足时,系统会利用这个分区将非活动进程的部分内存“交换”到磁盘上,从而释放内存空间。

使用分区作为交换空间

假设我们需要将/dev/sdb2分区设置为交换空间,操作步骤如下:

  1. 确保分区为空:确认目标分区没有存储重要数据。
  2. 初始化交换区:运行mkswap /dev/sdb2命令。
  3. 启用交换设备:执行swapon /dev/sdb2以激活该交换分区。
  4. 持久化设置:为了在系统重启后仍然保持此交换分区有效,需在/etc/fstab文件中添加相应的条目,类型应设为swap

示例/etc/fstab条目:

1
/dev/sdb2 none swap sw 0 0
  • 禁用交换:若要关闭交换分区,可以使用swapoff /dev/sdb2命令。

分配原则

通常建议分配的交换空间大小为实际物理内存的两倍。然而,鉴于现今系统的强大性能及充足的RAM容量,这一准则可根据实际情况灵活调整。对于大多数现代系统而言,除非有特殊需求,否则不一定需要遵循这一传统指导原则。

9 磁盘使用情况

为了监控磁盘的使用情况,Linux 提供了多种实用工具。以下是两个最常用的命令:dfdu

使用 df 查看文件系统利用率

通过运行以下命令,可以查看当前已挂载文件系统的利用率:

1
df -h

示例输出:

1
2
Filesystem     1K-blocks      Used   Available  Use% Mounted on
/dev/sda1 6.2G 2.3G 3.6G 40% /

这里的 -h 标志使得输出结果以人类可读的格式显示(例如 KB、MB、GB)。该命令能展示设备名称、容量使用情况及可用空间。

使用 du 分析目录和文件大小

如果需要进一步了解哪些文件或目录占用了大量磁盘空间,可以使用 du 命令。

1
du -h

此命令会显示当前所在目录下的磁盘使用情况。若要检查根目录下的磁盘使用情况,可以执行:

1
du -h /

但请注意,这种方式可能会产生大量输出,因为根目录包含了整个文件系统的文件信息。

区分 dfdu

尽管这两个命令在语法上相似,它们的功能却有明显区别:

  • 检查disk free:使用 df
  • 检查disk usage:使用 du

10 文件系统修复

在使用计算机过程中,文件系统可能会因为突发的断电或其他异常情况而受损,导致数据损坏。为了恢复系统的正常工作状态,可以利用 fsck(文件系统检查)命令来检查并尝试修复文件系统的错误。

使用 fsck 命令

通常情况下,当启动系统时,如果检测到文件系统可能存在不一致的问题,fsck 会自动运行以确保文件系统在挂载前处于良好状态。然而,在某些情况下,文件系统的损坏程度较高,需要用户手动干预进行修复。

执行以下命令以手动检查和修复文件系统:

1
sudo fsck /dev/sda

请注意,执行 fsck 操作时应确保目标文件系统未被挂载,以免造成进一步的数据损坏。建议在救援模式或通过其他可访问文件系统但不挂载的方式下运行此命令。

11 索引节点(Inodes)

文件系统不仅包含了实际的文件数据,还包含一个用于管理这些文件的数据库,即索引节点表。

什么是索引节点?

索引节点(inode)是该表中的一个条目,每个文件都有一个对应的索引节点。它记录了除文件名和文件内容外的所有信息,包括:

  • 文件类型:普通文件、目录、字符设备等
  • 所有者
  • 用户组
  • 访问权限
  • 时间戳:最后一次修改时间(mtime)、最后一次属性更改时间(ctime)、最后一次访问时间(atime)
  • 文件的硬链接数
  • 文件大小
  • 分配给文件的数据块数量
  • 指向文件数据块的指针——这是最为关键的部分

索引节点的创建

在文件系统创建时,会为索引节点分配空间。分配的空间量基于磁盘容量和其他因素通过算法决定。尽管较为少见,但与磁盘空间一样,索引节点也可能耗尽,导致无法创建新文件。使用命令 df -i 可以查看系统中剩余的索引节点数量。

查看索引节点信息

索引节点通过编号进行标识,新创建的文件会被分配一个顺序递增的索引节点号。然而,当删除文件后,其索引节点可以被重新使用,因此有时新文件可能会获得比其他现有文件更低的索引节点号。使用 ls -li 命令可查看索引节点号。

1
2
3
pete@icebox:~$ ls -li
140 drwxr-xr-x 2 pete pete 6 Jan 20 20:13 Desktop
141 drwxr-xr-x 2 pete pete 6 Jan 20 20:01 Documents

上述命令的第一列显示的是索引节点号。此外,还可以使用 stat 命令获取文件的详细信息,包括其索引节点相关数据。

1
2
3
4
5
6
7
8
9
pete@icebox:~$ stat ~/Desktop/
File: ‘/home/pete/Desktop/’
Size: 6 Blocks: 0 IO Block: 4096 directory
Device: 806h/2054d Inode: 140 Links: 2
Access: (0755/drwxr-xr-x) Uid: ( 1000/ pete) Gid: ( 1000/ pete)
Access: 2016-01-20 20:13:50.647435982 -0800
Modify: 2016-01-20 20:13:06.191675843 -0800
Change: 2016-01-20 20:13:06.191675843 -0800
Birth: -

索引节点如何定位文件?

索引节点指向实际存储文件数据的数据块。典型的文件系统中,每个索引节点包含15个指针。前12个直接指向文件的数据块;第13个指针指向一个包含更多指针的块;第14个指针指向另一个嵌套的指针块;第15个指针再次指向另一组指针块。这种结构使得无论文件大小如何,索引节点结构保持一致,同时能够有效地管理和引用不同大小的文件。较小的文件可通过前12个直接指针快速找到,较大的文件则需通过嵌套的指针链来定位。

12 符号链接(Symlinks)与硬链接(Hardlinks)

在Linux文件系统中,有两种主要类型的链接:符号链接(symlinks)和硬链接(hardlinks)。

符号链接

符号链接类似于Windows操作系统中的快捷方式。它是指向另一个文件名的别名。如果原始文件被删除或修改,可能会导致符号链接失效。创建符号链接时,使用ln -s命令指定目标文件和链接名称。

例如:

1
2
3
4
5
pete@icebox:~/Desktop$ echo 'myfile' > myfile
pete@icebox:~/Desktop$ ln -s myfile myfilelink

pete@icebox:~/Desktop$ ls -li
93403 lrwxrwxrwx 1 pete pete 6 Jan 21 21:39 myfilelink -> myfile

执行ls -li后, myfilelink 是一个指向 myfile 的符号链接。值得注意的是,符号链接拥有独立的索引节点号,并且不依赖于索引节点来实现跨文件系统的引用。

硬链接

硬链接则不同,它是直接指向同一索引节点的另一个文件。这意味着,如果你通过任何硬链接之一修改文件内容,所有相关联的硬链接都会反映这些更改。只有当与某个索引节点关联的所有硬链接都被删除时,该索引节点及其数据才会真正被删除。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pete@icebox:~/Desktop$ ln myfile2 myhardlink

pete@icebox:~/Desktop$ ls -li
total 16

151 -rw-rw-r-- 1 pete pete 7 Jan 21 21:36 myfile

93401 -rw-rw-r-- 2 pete pete 8 Jan 21 21:36 myfile2

93402 -rw-rw-r-- 1 pete pete 8 Jan 21 21:36 myfile3

93403 lrwxrwxrwx 1 pete pete 6 Jan 21 21:39 myfilelink -> myfile

93401 -rw-rw-r-- 2 pete pete 8 Jan 21 21:36 myhardlink

执行ls -li后,可以看到myfile2myhardlink共享相同的索引节点号。这意味着无论你通过哪个硬链接进行修改,两个文件的内容都将同步更新。硬链接的数量可以通过ls命令输出中的链接计数字段查看。

硬链接的一个关键限制是它们不能跨越不同的文件系统,因为每个文件系统的索引节点都是唯一的。相反,符号链接可以跨越文件系统,因为它们依赖于文件路径而非索引节点。

创建链接的命令

  • 创建符号链接

    1
    $ ln -s myfile mylink

    使用ln命令加上-s选项来创建一个指向myfile的符号链接mylink

  • 创建硬链接

    1
    $ ln somefile somelink

    创建硬链接时省略-s选项,直接指定源文件和链接名称即可。


[Linux]The Filesystem
https://erlsrnby04.github.io/2025/03/21/Linux-The-Filesystem/
作者
ErlsrnBy04
发布于
2025年3月21日
许可协议