深入理解 Linux Ext 系列文件系统:从磁盘物理结构到软硬链接

Linux Swap 子系统:架构、内存管理与虚拟化 Swap Linux Swap机制通过将不活跃内存页移至磁盘或压缩内存,扩展系统有效内存容量,缓解内存压力。传统架构中,逻辑Swap槽与物理存储绑定,导致资源浪费,尤其在使用Zswap等压缩技术时。为此,Vswap与Xswap提出虚拟化方案:前者以XArray实现灵活映射,支持多后端迁移;后者采用稀疏映射,简化管理但容量固定。二者在架构设计、资源记账与动态扩展上各有权衡,反映了内核开发中对性能、可维护性与灵活性的深层考量。 阅读详情

        在 Linux 系统中,文件系统是连接用户数据与硬件磁盘的核心桥梁。无论是日常的文件读写,还是系统的启动与运行,都离不开文件系统的高效管理。Ext 系列(Ext2/Ext3/Ext4)作为 Linux 下最经典的文件系统,其设计思想深刻影响了后续诸多文件系统的发展。本文将从磁盘物理结构入手,逐步剖析 Ext 系列文件系统的原理,带你理解分区、格式化、路径解析、挂载等关键过程,最终掌握软硬链接的本质与用途,构建完整的文件系统知识体系。

一、磁盘基础:从物理结构到逻辑地址

要理解文件系统,首先需要搞清楚 “文件存储的载体 —— 磁盘” 的工作原理。磁盘作为计算机中唯一的机械设备,其物理结构决定了数据的存储与读取方式,而逻辑地址则是操作系统与磁盘交互的 “通用语言”。

1.1 磁盘物理结构:机械臂与扇区的协作

机械磁盘的核心结构可类比为 “多叠光盘 + 可移动读写笔”,具体包括以下组件:

        盘片(Platter):圆形金属盘,表面涂有磁性材料,用于存储数据;一个磁盘通常包含多个盘片(如 2-8 片)。

        磁头(Head):每片盘片的上下两面各对应一个磁头,用于读取 / 写入磁盘表面的磁性信号;所有磁头固定在同一根磁头臂上,只能 “共进退”(同时移动到相同半径的磁道)。

        磁道(Track):盘片表面被划分成多个同心圆,每个同心圆就是一个磁道;磁道从外圈到内圈编号(0 磁道、1 磁道...),靠近主轴的磁道不存储数据(用于磁头停靠)。

        柱面(Cylinder):所有盘片中,半径相同的磁道共同构成一个柱面;由于磁头 “共进退”,柱面是磁盘访问的最小单位(切换柱面需要移动磁头臂,耗时较长)。

        扇区(Sector):每个磁道被切分成多个扇形区域,即扇区;扇区是磁盘最小存储单位,默认大小为 512 字节(部分新磁盘支持 4KB 扇区)。

磁盘容量的计算公式为:磁盘容量 = 磁头数 × 柱面数 × 每磁道扇区数 × 每扇区字节数例如,一个磁盘有 2 个磁头、1024 个柱面、每磁道 63 个扇区,则容量为 2 × 1024 × 63 × 512B = 64.8MB。

1.2 磁盘寻址方式:CHS 与 LBA 的转换

要读取磁盘上的数据,必须先定位到具体的扇区。操作系统早期采用 CHS 寻址,后来发展为更通用的 LBA 寻址。

1.2.1 CHS 寻址:基于物理结构的定位

CHS(Cylinder-Head-Sector,柱面 - 磁头 - 扇区)是最早的磁盘寻址方式,直接对应磁盘的物理结构:

        步骤 1:移动磁头臂,将所有磁头定位到目标柱面(确定半径);

        步骤 2:选择目标磁头(确定盘片的某一面);

        步骤 3:等待磁盘旋转,当目标扇区到达磁头下方时,开始读写。

局限性:CHS 寻址的地址位数有限(早期系统用 8 位存磁头、10 位存柱面、6 位存扇区),最大支持容量仅为 256 × 1024 × 63 × 512B = 8.4GB,无法满足大磁盘需求。

1.2.2 LBA 寻址:线性化的逻辑地址

为解决 CHS 的容量限制,操作系统引入了 LBA(Logical Block Address,逻辑块地址),将磁盘抽象为一个 “扇区数组”:

        每个扇区对应一个唯一的线性地址(从 0 开始编号),例如磁盘有 83886080 个扇区,则 LBA 地址范围是 0~83886079;

        操作系统只需使用 LBA 地址即可访问扇区,磁盘内部的固件(硬件电路) 会自动将 LBA 转换为 CHS 物理地址。

LBA 与 CHS 的转换公式(假设磁盘参数:磁头数 H、每磁道扇区数 S):

        CHS 转 LBA:LBA = 柱面号 C × (H × S) + 磁头号 Hd × S + 扇区号 Se - 1(扇区号从 1 开始,LBA 从 0 开始,需减 1);

        LBA 转 CHS:柱面号 C = LBA // (H × S)(整除,得到目标柱面);磁头号 Hd = (LBA % (H × S)) // S(取余后整除,得到目标磁头);扇区号 Se = (LBA % S) + 1(取余后加 1,得到目标扇区)。

例如,磁盘参数为 H=2、S=63,LBA=1000:C = 1000 // (2×63) = 7(第 7 个柱面);Hd = (1000 % 126) // 63 = 1(第 1 个磁头);Se = (1000 % 63) + 1 = 49(第 49 个扇区)。

从此,操作系统无需关心磁盘的物理结构,只需通过 LBA 地址即可访问任意扇区 —— 磁盘在逻辑上成为了一个 “一维扇区数组”。

二、文件系统的核心概念:块、分区与 inode

磁盘的逻辑地址解决了 “如何定位单个扇区” 的问题,但文件系统需要解决 “如何组织多个扇区存储文件” 的问题。为此,文件系统引入了 “块”“分区”“inode” 三个核心概念,构建了从磁盘到文件的分层管理模型。

2.1 块(Block):文件存取的最小单位

扇区(512B)太小,若每次读写都操作单个扇区,会导致系统调用频繁、效率低下。因此,文件系统将连续的多个扇区组合成一个 “块”,作为文件存取的最小单位:

        常见块大小为 4KB(即 8 个扇区),也支持 1KB、2KB、8KB 等(由格式化时指定,不可修改);

        块地址与 LBA 的转换:块号 = LBA // 块扇区数(如 LBA=1000,块大小 4KB(8 扇区),则块号 = 1000//8=125);LBA = 块号 × 块扇区数 + 块内扇区号(如块号 = 125,块内第 3 个扇区,LBA=125×8+3=1003)。

通过 stat 命令可查看文件的块信息:

[whb@bite-alicloud stdio]$ stat main.c
  File: main.c
  Size: 488        Blocks: 8          IO Block: 4096   regular file
# Size:文件实际大小(488B);Blocks:占用的块数(8×512B=4KB,即 1 个 4KB 块);IO Block:块大小(4096B=4KB)

2.2 分区(Partition):磁盘的 “逻辑切片”

一块磁盘容量可能很大(如 1TB),若直接管理整个磁盘,会导致文件系统过于庞大、故障风险高。因此,磁盘需要先进行分区,将其划分为多个独立的 “逻辑磁盘”(如 Windows 的 C/D/E 盘,Linux 的 /dev/vda1、/dev/vda2):

        分区本质:指定磁盘的 “起始柱面” 和 “结束柱面”,将连续的柱面划分为一个分区;

        分区单位:柱面(由于磁头 “共进退”,柱面是最小的连续存储单元);

        Linux 分区表示:磁盘设备文件为 /dev/vda(第一块虚拟磁盘)、/dev/sda(第一块物理磁盘),分区为 /dev/vda1(第一块磁盘的第一个分区)、/dev/vda2 等。

通过 fdisk -l 命令可查看磁盘分区信息:

[root@bite-alicloud ~]# fdisk -l
Disk /dev/vda: 42.9 GB, 42949672960 bytes, 83886080 sectors
Units = sectors of 1 * 512 = 512 bytes
Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048    83875364    41936658+  83  Linux
# /dev/vda1:分区设备名;Start/End:起始/结束扇区;Blocks:分区大小(41936658×512B≈20GB);System:文件系统类型(Linux)

2.3 inode:文件属性的 “身份证”

文件的本质是 “属性 + 内容”:

        内容:存储在数据块(Block)中;

        属性:如文件名、大小、权限(rwx)、所有者、修改时间等,需要单独存储 —— 这就是 inode(Index Node,索引节点)的作用。

2.3.1 inode 的核心特征

        唯一性:每个文件对应一个唯一的 inode,每个 inode 有一个唯一的 inode 号(以分区为单位编号,不可跨分区);

        固定大小:inode 大小通常为 128 字节或 256 字节(由格式化时指定),无论文件内容多大,其 inode 大小固定;

        属性存储:inode 中存储文件的所有属性,但不包含文件名(文件名存储在目录中,后续详解)。

通过 ls -i 命令可查看文件的 inode 号:

[whb@bite-alicloud stdio]$ ls -li
1052007 -rw-rw-r-- 1 whb whb 488 Oct 17 19:06 main.c
# 1052007:inode 号;main.c:文件名(与 inode 号对应)
2.3.2 inode 结构体(Ext2 为例)

inode 的具体结构定义在 Linux 内核源码中(/usr/src/kernels/xxx/include/linux/ext2_fs.h),核心字段如下:

struct ext2_inode {
    __le16 i_mode;        // 文件类型与权限(如 0644 表示普通文件,所有者读写)
    __le16 i_uid;         // 所有者 UID
    __le32 i_size;        // 文件大小(字节)
    __le32 i_atime;       // 最后访问时间
    __le32 i_mtime;       // 内容最后修改时间
    __le32 i_ctime;       // 属性最后修改时间
    __le16 i_gid;         // 所属组 GID
    __le16 i_links_count; // 硬链接数
    __le32 i_blocks;      // 占用的块数
    __le32 i_block[EXT2_N_BLOCKS]; // 数据块指针(EXT2_N_BLOCKS=15,指向存储内容的块)
};

其中,i_block 是 inode 与数据块的 “桥梁”—— 通过这 15 个指针,可找到文件内容所在的所有数据块(后续详解指针映射逻辑)。

三、Ext2 文件系统:块组与分层管理

有了块、分区、inode 的基础,接下来我们深入 Ext2 文件系统的核心 —— 它通过 “块组(Block Group)” 将分区划分为多个独立的管理单元,实现高效的文件组织与故障隔离。

3.1 Ext2 整体架构:从分区到块组

Ext2 文件系统将整个分区划分为若干个大小相等的块组(Block Group),每个块组的结构完全相同。这种设计的优势在于:

        减少磁头移动距离(同一文件的内容尽量存储在同一块组);

        故障隔离(单个块组损坏不影响其他块组)。

分区的结构如下(从左到右):

  1. 引导块(Boot Block):1KB 大小,存储分区引导信息(如 GRUB 引导程序),不属于任何块组;
  2. 块组 0 ~ 块组 N:每个块组包含超级块、块组描述符表、位图、inode 表、数据块等组件。

3.2 块组内部结构:6 大核心组件

每个块组是 Ext2 文件系统的 “最小管理单元”,其内部结构如下(从上到下):

3.2.1 超级块(Super Block):文件系统的 “说明书”

超级块存储整个文件系统的全局信息,是文件系统的核心,主要内容包括:

        块总数、inode 总数、空闲块数、空闲 inode 数;

        块大小、inode 大小、每个块组的块数 /inode 数;

        最近挂载时间、最近写入时间、文件系统状态(如正常 / 错误)。

关键特性:超级块在每个块组的开头都有一份拷贝(块组 0 必须有,其他块组可选),用于防止超级块损坏导致整个文件系统失效。

3.2.2 块组描述符表(GDT):块组的 “索引卡”

块组描述符表由多个块组描述符(struct ext2_group_desc)组成,每个块组对应一个描述符,记录该块组的具体信息:

        块位图、inode 位图、inode 表的起始块号;

        该块组的空闲块数、空闲 inode 数、目录数。

与超级块类似,GDT 在每个块组中也有拷贝,确保可靠性。

3.2.3 块位图(Block Bitmap):数据块的 “占用状态表”

块位图是一个二进制数组,每个 bit 对应一个数据块,用于标记数据块是否空闲:

        bit=0:数据块空闲,可分配;

        bit=1:数据块已占用,不可分配。

例如,块位图的第 5 个 bit 为 1,表示该块组的第 5 个数据块已被使用。通过块位图,文件系统可快速找到空闲的数据块,无需遍历所有块。

3.2.4 inode 位图(Inode Bitmap):inode 的 “占用状态表”

与块位图类似,inode 位图也是一个二进制数组,每个 bit 对应一个 inode,标记 inode 是否空闲:

        bit=0:inode 空闲,可分配;

        bit=1:inode 已占用,不可分配。

例如,inode 位图的第 10 个 bit 为 1,表示该块组的第 10 个 inode 已被使用。

3.2.5 inode 表(Inode Table):文件属性的 “仓库”

inode 表是连续的块,用于存储该块组所有 inode 的具体内容(即 struct ext2_inode 结构体)。每个 inode 占固定大小(如 128 字节),因此 inode 表的大小 = 块组 inode 数 × inode 大小。

例如,一个块组有 1024 个 inode,每个 inode 128 字节,则 inode 表占用 1024 × 128B = 128KB,若块大小为 4KB,则占用 32 个块。

3.2.6 数据块(Data Blocks):文件内容的 “存储区”

数据块是块组的最后一部分,用于存储文件的实际内容。根据文件类型,数据块的用途不同:

        普通文件:存储文件的文本、二进制等数据;

        目录:存储该目录下的 “文件名 + inode 号” 映射关系(目录也是文件,后续详解);

        链接文件:硬链接不占用数据块(仅复用 inode),软链接占用数据块(存储目标文件路径)。

3.3 inode 与数据块的映射:15 个指针的巧妙设计

inode 中的 i_block[15] 字段是连接文件属性与内容的关键,它通过 15 个指针实现数据块的高效映射,分为以下四种类型:

  1. 12 个直接指针:前 12 个指针直接指向存储文件内容的数据块;若块大小为 4KB,这 12 个指针可存储 12 × 4KB = 48KB 的文件。
  2. 1 个一级间接指针:第 13 个指针指向一个 “间接块”,该块中存储的是 “数据块的指针”(而非内容);若每个指针 4 字节,一个间接块可存储 4KB / 4B = 1024 个指针,对应 1024 × 4KB = 4MB 的文件。
  3. 1 个二级间接指针:第 14 个指针指向一个 “一级间接块”,该块中的每个指针又指向一个 “二级间接块”,二级间接块再指向数据块;可存储 1024 × 1024 × 4KB = 4GB 的文件。
  4. 1 个三级间接指针:第 15 个指针指向一个 “二级间接块”,再嵌套一层间接块;可存储 1024 × 1024 × 1024 × 4KB = 4TB 的文件。

这种分层映射设计,既保证了小文件的高效访问(直接指针),又支持超大文件的存储(多级间接指针)。

3.4 文件创建的完整流程:从 inode 到目录

以创建 touch abc 为例,Ext2 文件系统的处理流程如下:

  1. 分配 inode:遍历 inode 位图,找到一个空闲 inode(如 inode 号 263466),将其标记为占用,并写入文件属性(如权限 0644、所有者 UID 等)。
  2. 分配数据块:若文件有内容(如 echo "hello" > abc),遍历块位图,找到空闲数据块(如块 300、500、800),将数据写入这些块,并在 inode 的 i_block 中记录块号。
  3. 更新目录:目录文件的内容是 “文件名 + inode 号” 的映射,系统在当前目录的数据块中添加一条记录(abc:263466),建立文件名与 inode 的关联。
  4. 更新元数据:减少超级块和块组描述符表中的 “空闲 inode 数” 和 “空闲块数”,更新最近写入时间。

四、目录与路径:文件访问的 “导航系统”

我们平时访问文件时,使用的是 “路径 + 文件名”(如 /home/whb/main.c),但文件系统真正识别的是 inode 号。那么,目录和路径是如何将 “文件名” 转换为 “inode 号” 的呢?

4.1 目录的本质:存储 “文件名 - inode” 映射的文件

在 Linux 中,目录也是文件—— 它的属性存储在 inode 中,内容存储在数据块中,而数据块的内容就是 “文件名与 inode 号的映射表”。

例如,/home/whb 目录的数据块内容可能如下:

文件名inode 号
.1596259(当前目录的 inode 号)
..1596258(父目录 /home 的 inode 号)
main.c1596260(普通文件的 inode 号)
test1596261(子目录的 inode 号)

通过 readdir 系统调用可读取目录的内容(即 “文件名 - inode” 映射),示例代码如下:

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if (argc != 2) { fprintf(stderr, "Usage: %s <directory>\n", argv[0]); exit(1); }
    DIR *dir = opendir(argv[1]); // 打开目录
    if (!dir) { perror("opendir"); exit(1); }
    
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) { // 读取目录内容
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
        printf("Filename: %s, Inode: %lu\n", entry->d_name, (unsigned long)entry->d_ino);
    }
    closedir(dir);
    return 0;
}

运行结果(读取根目录 /):

[whb@bite ~]$ ./readdir /
Filename: home, Inode: 786433
Filename: etc, Inode: 262145
Filename: bin, Inode: 13

4.2 路径解析:从根目录到目标文件的 “递归导航”

访问文件时,系统需要将路径(如 /home/whb/main.c)解析为对应的 inode 号,流程如下:

  1. 从根目录开始:根目录(/)的 inode 号是固定的(通常为 2),系统开机后直接加载其 inode;
  2. 解析每一级目录:
    • 打开根目录,根据 “home” 文件名找到对应的 inode 号(如 786433);
    • 打开 /home 目录,根据 “whb” 文件名找到对应的 inode 号(如 1596259);
    • 打开 /home/whb 目录,根据 “main.c” 文件名找到对应的 inode 号(如 1596260);
  3. 访问目标文件:通过 main.c 的 inode 号,找到其数据块,读取文件内容。

路径缓存(dentry 缓存):为避免每次访问文件都从根目录重新解析,Linux 内核会在内存中维护一个 dentry 缓存(struct dentry 结构体),存储已解析的 “路径 - inode” 映射。下次访问同一文件时,直接从缓存中获取 inode,大幅提升效率。

struct dentry 结构体的核心字段:

struct dentry {
    struct inode *d_inode;    // 对应的 inode 指针
    struct dentry *d_parent;  // 父目录的 dentry 指针
    struct qstr d_name;       // 文件名
    struct list_head d_subdirs;// 子目录的 dentry 链表
};

这些字段在内存中形成一棵 “目录树”,与磁盘上的目录结构一致,实现路径的快速查找。

五、挂载:分区与目录的 “绑定”

分区在格式化后,虽然包含了 Ext2 文件系统的结构,但仍无法直接使用 —— 需要通过 “挂载(mount)” 将分区与某个目录绑定,才能通过该目录访问分区中的文件。

5.1 挂载的本质:建立文件系统与目录树的关联

挂载的核心是 “将分区的文件系统挂载到 Linux 目录树的某个节点(挂载点)”,使得:

        访问挂载点目录时,实际访问的是分区中的文件系统;

        分区中的文件被整合到 Linux 统一的目录树中,用户无需关心分区边界。

例如,将 /dev/vda1 分区(Ext2 文件系统)挂载到 /mnt/mydisk 目录后,ls /mnt/mydisk 显示的是 /dev/vda1 分区中的文件。

5.2 挂载操作的实际流程

以挂载一个 Ext4 格式的磁盘镜像文件为例:

  1. 创建挂载点:创建一个空目录作为挂载点(如 /mnt/mydisk);

    bash

    [whb@bite ~]$ mkdir /mnt/mydisk
    
  2. 准备磁盘镜像:创建一个 5MB 的空文件,格式化为 Ext4 文件系统;

    bash

    [whb@bite ~]$ dd if=/dev/zero of=./disk.img bs=1M count=5 # 创建 5MB 空文件
    [whb@bite ~]$ mkfs.ext4 disk.img # 格式化为 Ext4 文件系统
    
  3. 执行挂载:使用 mount 命令将磁盘镜像挂载到 /mnt/mydisk;

    bash

    [whb@bite ~]$ sudo mount -t ext4 ./disk.img /mnt/mydisk
    # -t ext4:指定文件系统类型;./disk.img:要挂载的设备(这里是磁盘镜像);/mnt/mydisk:挂载点
    
  4. 验证挂载:通过 df -h 命令查看挂载结果;

    bash

    [whb@bite ~]$ df -h
    Filesystem      Size  Used Avail Use% Mounted on
    ./disk.img      4.9M   24K  4.5M   1% /mnt/mydisk
    
  5. 卸载分区:使用 umount 命令解除挂载(挂载点目录必须为空);

    bash

    [whb@bite ~]$ sudo umount /mnt/mydisk
    

5.3 循环设备(Loop Device):将文件作为块设备

在上述例子中,./disk.img 是一个普通文件,但通过 循环设备(如 /dev/loop0),它被模拟为一个块设备,从而可以被挂载:

        循环设备是 Linux 中的一种伪设备(/dev/loop0~/dev/loop7),允许将普通文件作为块设备使用;

  mount 命令会自动分配一个空闲的循环设备,将文件与设备绑定,再挂载设备到目录。

通过 ls /dev/loop* 可查看系统中的循环设备:

[whb@bite ~]$ ls /dev/loop* -l
brw-rw---- 1 root disk 7, 0 Oct 17 18:24 /dev/loop0
brw-rw---- 1 root disk 7, 1 Oct 17 18:24 /dev/loop1
# brw:块设备文件;7,0:主设备号和次设备号

六、软硬链接:文件的 “别名” 与 “快捷方式”

在 Linux 中,多个文件名可以对应同一个文件,这就是 “链接(Link)” 的作用。链接分为硬链接(Hard Link)和软链接(Symbolic Link),二者的实现原理和用途截然不同。

6.1 硬链接:共享 inode 的 “别名”

硬链接是 “多个文件名对应同一个 inode 号”,本质是在目录中添加一条 “文件名 - inode” 映射记录,不创建新的 inode 和数据块。

6.1.1 硬链接的创建与特性

通过 ln 源文件 硬链接文件 创建硬链接:

[whb@bite ~]$ touch abc # 创建源文件,inode 号 263466
[whb@bite ~]$ ln abc def # 创建硬链接 def
[whb@bite ~]$ ls -li abc def
263466 -rw-rw-r-- 2 whb whb 0 Oct 28 20:32 abc
263466 -rw-rw-r-- 2 whb whb 0 Oct 28 20:32 def
# 两个文件的 inode 号相同(263466),硬链接数为 2(i_links_count=2)

硬链接的核心特性:

        共享 inode:硬链接文件与源文件的 inode 号相同,修改其中一个文件的内容,另一个文件也会同步变化;

        硬链接数:inode 的 i_links_count 字段记录硬链接的数量,创建硬链接时该值加 1,删除时减 1;只有当 i_links_count 为 0 时,才会释放 inode 和数据块;

        不可跨分区:inode 号以分区为单位编号,跨分区的 inode 号可能重复,因此硬链接无法跨分区创建;

        不能链接目录:若允许硬链接目录,会导致目录树出现循环(如 a/b 链接到 a),破坏路径解析逻辑。

6.1.2 硬链接的用途

        目录的 . 和 ..:每个目录的 . 是指向自身的硬链接(硬链接数 +1),.. 是指向父目录的硬链接(父目录的硬链接数 +1);

        文件备份:创建硬链接可作为文件的 “轻量级备份”,不占用额外磁盘空间,且修改源文件时备份文件同步更新。

6.2 软链接:存储路径的 “快捷方式”

软链接(符号链接)是 “一个独立的文件,其内容是目标文件的路径”,本质是创建一个新的 inode 和数据块,数据块中存储的是目标文件的路径。

6.2.1 软链接的创建与特性

通过 ln -s 源文件 软链接文件 创建软链接:

[whb@bite ~]$ ln -s abc abc.s # 创建软链接 abc.s
[whb@bite ~]$ ls -li abc abc.s
263466 -rw-rw-r-- 2 whb whb 0 Oct 28 20:32 abc
263568 lrwxrwxrwx 1 whb whb 3 Oct 28 20:33 abc.s -> abc
# abc.s 的 inode 号(263568)与源文件不同;权限为 lrwxrwxrwx(l 表示软链接);-> 表示指向目标文件

软链接的核心特性:

        独立 inode:软链接是一个独立的文件,有自己的 inode 和数据块(数据块存储目标路径);

        依赖目标路径:访问软链接时,系统会根据其存储的路径解析到目标文件;若目标文件被删除或移动,软链接会变成 “无效链接”(显示为红色闪烁);

        可跨分区:软链接存储的是目标文件的路径(如 /home/whb/abc),与分区无关,因此可跨分区创建;

        可链接目录:软链接可以链接目录(如 ln -s /home/whb /tmp/whb),不会导致目录树循环(因为软链接有独立 inode,路径解析时会识别并跳过)。

6.2.1 软链接的用途

        快捷方式:为深层目录或文件创建软链接,简化访问路径(如 ln -s /usr/local/jdk1.8.0_301 /usr/local/jdk);

        版本切换:通过修改软链接的指向,实现软件版本的快速切换(如 ln -s jdk1.8 jdk,切换版本时只需重新创建软链接指向 jdk11)。

6.3 软硬链接对比

特性硬链接(Hard Link)软链接(Symbolic Link)
inode 号与源文件相同独立 inode 号
数据块与源文件共享存储目标文件路径
跨分区不支持支持
链接目录不支持支持
目标文件删除后仍可访问(inode 未释放)无效链接(红色闪烁)
权限与源文件相同(权限位不生效)固定为 lrwxrwxrwx(实际权限由目标文件决定)

七、总结:Ext 系列文件系统的核心逻辑

Ext 系列文件系统的设计围绕 “高效管理磁盘空间、可靠存储文件” 展开,其核心逻辑可总结为以下几点:

  1. 分层抽象:从磁盘物理结构(CHS)到逻辑地址(LBA),再到文件系统(块组、inode、数据块),每一层抽象都屏蔽了底层复杂性,为上层提供统一接口;
  2. 分离存储:文件的 “属性(inode)” 与 “内容(数据块)” 分离存储,通过 inode 的指针实现关联,既便于属性查询,又利于内容的高效读写;
  3. 块组管理:将分区划分为多个块组,每个块组包含完整的管理组件(超级块、位图、inode 表),实现故障隔离和高效访问;
  4. 路径解析:通过目录存储 “文件名 - inode” 映射,结合路径缓存(dentry),实现从路径到 inode 的快速转换;
  5. 灵活链接:硬链接实现文件的 “多别名” 共享,软链接实现 “跨分区、跨目录” 的快捷访问,满足不同场景需求。
北京途游游戏后端开发面经 北京途游游戏后端开发面经 我面试岗位是基于Python的后端开发工程师,主要是搞游戏的服务器开发。面试一共分了两轮,之后说是看看其他的候选人再定,感觉凉凉~~ 由于受到此次新型冠状病毒疫情的影响,本次面试采用视频面试的方式,下面是面试的时候面试官提的问题,python的基础知识还是问的比较多的。  一面:(32分钟微信视频)  简单做下自我介绍,   1.说一下你开发过的项目,挑一个说下你都做了... 阅读详情

相关推荐

基于PI双闭环解耦控制的三相SVPWM电压型逆变器(1)--数学模型

三相电压型逆变器、双PI控制、SVPWM、解耦

weixin_58670090的博客 1万+

【Linux】万字详解:Linux文件系统与软硬链接

详细讲解了linux下底层文件系统以及软硬链接

You build it, you run it 2777

开源大模型推理GPU资源评估以及优化

随着大模型的火热很多项目中都使用到了开源大模型,这时候准确评估大模型的GPU资源非常重要,主要有下面几个方面:GPU是昂贵的资源。高估内存需求可能导致在硬件上的不必要支出,而低估则可能导致系统故障或性能下降。:适当的内存管理确保模型高效运行,能够更快地响应用户并处理更多并发请求。:随着需求的增长,理解内存需求对于在不牺牲性能或产生高昂成本的情况下扩展服务至关重要。尽管其重要性显而易见,但计算用于服务大型语言模型(LLM)的GPU内存并不简单。

优快云DN的博客 3115

深入理解 Ext 系列文件系统:从磁盘物理到文件系统原理

本文将深入解析Linux文件系统的核心机制,重点探讨Ext系列文件系统的设计原理。文章从磁盘物理结构入手,详细介绍了磁盘的CHS寻址方式(磁头、柱面、扇区)及其与LBA逻辑块地址的转换关系。通过分析磁盘的逻辑抽象过程,揭示了文件系统如何将三维物理结构转化为一维线性空间进行管理。 在文件系统层面,文章重点讲解了"块"的概念(由8个512字节扇区组成4KB块)、分区原理(以柱面为最小单位)以及inode索引节点的核心作用。inode作为存储文件元信息的128字节数据结构,包含文件权限、大小、

zoelinkailuo的博客 1286

微调BERT进行中文文本分类任务(Pytorch代码实现)

BERT(Bidirectional Encoder Representation from Transformers)是2018年10月由Google AI研究院提出的一种预训练模型。其模型结构由多层Transformer的Encoder堆叠而成,在大规模语料中进行预训练后,迁移到下游任务,仅进行参数微调训练,就能显著提升性能。本文聚焦于微调中文BERT进行新闻标题分类任务的代码实现。

Iswayzw的博客 1万+

向量库深度解析:选型、索引原理与生产实践

本文系统解析五大主流向量库(pgvector、Milvus、Weaviate、ChromaDB、Faiss)的定位、优缺点与适用场景,深入拆解FLAT、IVF、HNSW等核心索引原理,并重点分析Milvus的Compaction机制。针对数据治理场景,提供精准选型建议:中小规模优先pgvector或Weaviate,超大规模选择Milvus,开发测试推荐ChromaDB。核心索引推荐HNSW,兼顾检索速度与召回率。全文从理论到实践,为开发者提供清晰的向量库选型逻辑与生产落地指南。

a123147abc的博客 360

磁盘到 inode:深入理解 Linux ext 文件系统底层原理

文件系统是操作系统管理存储的核心机制,却常常被开发者视为“黑盒”。本文将从磁盘硬件原理出发,深入浅出地剖析 Linux 中经典的ext 文件系统如何组织数据、管理文件,并揭示inode、块、软硬链接等关键概念的底层实现。通过理解这些机制,你不仅能更高效地使用文件系统,还能在调试、优化乃至数据恢复时多一份底气。让我们一起揭开文件系统的神秘面纱!

2302_80105876的博客 8214

STM32CubeIDE中文注释变乱码终极解决方案:3步设置永久解决锟斤拷问题!

你是否在STM32CubeIDE中遇到过这样的崩溃场景?——精心编写的中文注释在重新生成代码后变成“锟斤拷”乱码,不仅影响代码可读性,反复修改更是浪费大量时间!作为STM32开发者,我曾被这个问题困扰许久,试过修改软件设置、工程编码却始终治标不治本。直到发现这个基于Java环境变量的终极解决方案,才彻底解决了中文乱码难题。

smart_boy__的博客 2955

【探索Linux】P.13(文件系统 | 软硬链接 | 动态库和静态库)

本文将深入讨论 Linux 系统中的文件系统、软硬链接、动态库和静态库等概念。首先,我们介绍了 Linux 文件系统的基本概念和组成部分,包括文件和目录的层次结构以及常见的文件系统类型。接着,我们探讨了软硬链接的区别和使用方法,解释了它们在 Linux 系统中的应用场景。然后,我们详细说明了动态库和静态库的概念、特点以及使用方式,帮助读者理解它们在程序开发和编译过程中的作用。通过本文的阐述,读者将对 Linux 系统中文件系统、软硬链接、动态库和静态库有更深入的了解,为其日后的应用和开发提供有价值的指导。

Yawesh的博客 2067

生产环境下oracle19c rac恢复节点2

现状:目前节点1数据库集群服务处于正常,节点2服务器由于系统故障无法恢复,确认系统重装。目标:不影响业务的情况下,重新把节点2添加回集群中。

sqlora的专栏 865

OpenClaw 从新手到中级完整教程【完整 持续更新版】

OpenClaw(曾用名 ClawdBot/Moltbot)是 2026 年最火的开源 AI Agent 项目,GitHub 已获得超过 68,000 星标。它不是普通的聊天机器人,而是一个真正能够执行任务的个人 AI 助理。

FeelTouch Labs 3113

Linux系统编程--Ext系列文件系统

摘要:本文介绍了Ext系列文件系统的概念及其与磁盘结构的关系。首先阐述了文件系统的基本功能——管理未打开文件,随后详细解析了磁盘的物理结构(盘片、磁头、传动臂等)和存储结构(磁道、扇区、柱面)。重点描述了CHS寻址方式和磁盘逻辑结构,将磁盘抽象为三维数组,进而转换为LBA地址。通过对比磁带结构,说明了磁盘数据的线性读取逻辑,并举例说明了LBA地址与CHS定位的转换过程。文章从硬件层到操作系统层,系统性地讲解了磁盘管理的基础原理。

Tanecious的博客 1174

[工作流节点10] 获取多条数据并循环执行 —— 明道云批处理自动化实战

本文系统介绍了明道云工作流中"获取多条数据+循环执行"的批处理功能。该功能通过筛选数据集合并逐条处理,适用于批量通知、数据更新等场景。文章详细解析了功能配置方法,包括数据筛选、循环设置和异常处理,并提供了合同到期提醒等典型应用案例。同时强调了数据量控制、分批处理、错误处理等优化策略,帮助用户实现高效批量自动化。这一功能组合能将业务从单条处理升级为批量驱动,显著提升工作效率。

每日出拳老爷子的博客 454

【Linux】十五.《深入 Linux 文件系统:磁盘、分区、inode 与软硬链接全解》

局部性原理:一次读 4 KB 可以覆盖更多未来可能访问的数据减少 I/O 次数:传输同样数据量,大块 I/O 效率更高与内存页大小对齐:避免额外的拆分与合并开销磁盘硬件本身也支持一次读多个连续扇区。

2501_93351213的博客 1610

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Linux--磁盘寻址:从 CHS 到 LBA 的深度解码之旅

本文聚焦 Linux 磁盘的 CHS 与 LBA 地址,先阐释文件系统核心作用及理解 Ext 文件系统的意义。从硬件世界(磁盘、服务器、机柜、机房)的协同,讲解磁盘物理结构,介绍 CHS 寻址的扇区、磁头、磁道、柱面概念,再引出 LBA 线性寻址,说明 CHS 与 LBA 相互转换公式及逻辑,展现磁盘寻址从物理到逻辑抽象的演进,帮助理解 Linux 磁盘数据存储与访问机制 。

2401_83191546的博客 1380

【Linux】文件系统和软硬链接

前面我们学习文件相关的知识,如文件操作等,文件都是被进程打开(内存文件),根据冯诺依曼体系结构,被打开的文件一定会被加载到内存,由操作系统管理。Linux学习目录但并不是所有的文件都会被进程打开,那么没有打开的文件就只能在磁盘上呆着(磁盘文件)。当然了,没有打开的文件也应当进行管理,我们把做这部分管理工作称之为文件系统。文件系统属于操作系统中的一部分,通常通过磁盘或其他存储介质来管理文件(路径问题,存储问题,获取问题内容+属性,删除修改等效率问题)。因此,在学习文件系统之前,我们首先需要认识磁盘。

Weraphael的博客 1222

Linux系统编程:Ext文件系统

本文详细介绍了磁盘的物理和逻辑结构。物理层面,磁盘由多个盘片组成,通过磁头、磁道、扇区等结构实现数据存储,容量计算公式为:磁头数×磁道数×每道扇区数×每扇区字节数。逻辑层面,操作系统将磁盘抽象为线性数组,使用LBA地址管理。文件系统采用分区管理,每个分区包含BootBlock和多个块组,块组内通过inode和block分别存储文件属性和内容,并使用位图记录使用情况。文章还介绍了软硬链接的区别:软链接是独立文件存储目标路径,硬链接则是多个文件名共享同一inode。最后说明了文件创建/删除时操作系统对inode

chenyuhao2024的博客 683

【Linux】第5期 深入理解 Linux 基础 IO 与 Ext 文件系统:从系统调用到磁盘底层

本文深入探讨了Linux系统中的文件IO机制与文件系统原理。首先介绍了Linux"一切皆文件"的设计哲学,包括普通文件、设备、进程间通信等资源的统一抽象。然后从用户态的C语言标准IO接口(fopen/fread/fwrite等)入手,详细解析了系统调用层(open/read/write等)的实现机制。重点讲解了文件描述符的本质——它是进程文件描述符表的数组索引,并通过files_struct和struct file结构体揭示了内核如何管理打开的文件。文章还涉及文件定位、标准流、位图标志位传递等关键技术点,为

2501_93298789的博客 256

理解 Linux 动态库加载:LD_LIBRARY_PATH

flyfish

二分掌柜的 331

Linux 磁盘满了怎么排查?df / du / find 三步定位大文件

Linux 磁盘满排查三步法:df -h 定位分区、du 逐层下钻、find 按大小和时间抓大文件,附 inode 耗尽、文件已删未释放、du 与 df 不一致等经典坑的解决方案。

weixin_38291577的博客 218

Linux-iostat命令详解

Linux命令学习记录

m0xin的博客 97

【Linux】APT 本地 deb 安装与 `-f` 参数总结笔记

apt install ./xx.deb 可自动解析并安装依赖,无需 -f;-f 仅用于修复已损坏的依赖状态,非首次安装时必需。apt install -f 可单独运行,修复 broken dependencies。两者职责不同:前者是安装与依赖解决,后者是故障修复。完全离线时需提前准备依赖包或本地源。

hknaruto的专栏 209

Linux 服务器性能排查手册(2026):CPU、内存、磁盘IO、网络四大瓶颈定位

iptables 四表五链模型、firewalld zone 信任级别、云安全组与主机防火墙的关系与优先级,避坑改了防火墙把自己挡在服务器外面的翻车事故。

2502_91473995的博客 287

Linux rm 误删文件恢复实操教程

Linux使用rm删除文件时,并不会直接抹除磁盘上的数据,只是移除文件索引,让系统不再识别这块空间。只要没有写入新数据,原有扇区内容就会保留。新文件写入才有可能覆盖这些区域,一旦覆盖就很难找回。恢复的本质就是扫描磁盘,找到这些还存在、但索引丢失的数据条目,再把它们导出保存到其他分区。越早停止写入,恢复成功的概率越高。

海天数据恢复-winhex数据恢复教程 224

Linux 磁盘 100% 但 du 查不出东西,五种情况逐个排

监控告警说根分区 100%,登录上去 du -sh /* 加起来只有 12GB,df 显示 40GB 已用。差了快 30GB,du 找不到任何东西。这种情况基本都是"文件被删了但进程还开着",但也可能是别的原因。这篇按可能性排一下顺序。

2408_89646393的博客 163

Linux sudo

如果输出 → 无 sudo 权限 如果输出 → 拥有全部 sudo 权限 辅助验证命令 ⚠️ 注意:在 wheel 组 ≠ 一定能 sudo,必须 开启 Ubuntu/Debian: ✅ 重要:修改组之后,用户要重新登录才生效! 或者执行 临时生效 看到这行(没有 #注释)才生效: 方式 2:visudo 直接单独给用户授权(精细化权限) 找到 ,下面添加一行: 自带语法校验,写错会告警,不要直接 vim 改 ,写错直接 sudo 炸掉! 想免密 su

fengliyang_的博客 178

Windows/Linux下强实时运动控制内核(二):基于Qt的Delta机械手的开发应用

强实时运动控制内核MotionRT750下Qt开发Delta机械手的完整开发流程。

weixin_57350300的博客 240
上一篇: 深入理解 Linux 基础 IO:从文件概念到自定义 Shell 重定向
下一篇: 深入理解 Linux 动静态库:从制作到加载的完整指南
cpparf
博客等级 码龄2年 48粉丝 65原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值