Linux 核心知识体系:文件系统结构与启动过程深度解析

1. Linux 文件系统结构(FHS)

文件系统层次结构标准(Filesystem Hierarchy Standard,FHS) 是 Linux 操作系统中文件和目录布局的规范。它确保了不同 Linux 发行版之间的一致性,便于软件管理、系统维护和可移植性。

FHS 的核心理念是将系统文件和用户数据、静态数据和可变数据进行逻辑分离,以实现系统稳定性、可管理性和多用户兼容性。

1.1 FHS 主要目录及其用途

  • / (根目录)
    • 文件系统层次结构的起点,所有其他目录和文件都在其下。
    • 只包含系统启动和运行所需的最少文件和目录。
  • /bin (用户二进制文件)
    • 所有用户都可用的基本命令,如 ls, cp, mv。这些命令是单用户模式下系统启动和维护所必需的。
  • /sbin (系统二进制文件)
    • 系统管理员使用的基本系统管理命令,如 fdisk, mkfs, reboot。通常用于系统启动、恢复和维护。
  • /etc (配置文件)
    • 所有系统范围的配置文件,如 /etc/passwd, /etc/group, 服务配置文件。通常是文本文件。
  • /dev (设备文件)
    • 设备文件,是操作系统与硬件设备交互的接口,如 /dev/sda (硬盘), /dev/tty0 (终端)。
  • /proc (进程信息虚拟文件系统)
    • 虚拟文件系统,提供内核和进程的实时信息,如 /proc/cpuinfo, /proc/meminfo。内容在内存中动态生成。
  • /sys (系统文件系统)
    • 虚拟文件系统,提供结构化的内核数据和硬件设备信息,用于设备模型和驱动程序状态,如 /sys/class/net
  • /var (可变数据文件)
    • 在系统正常运行期间会频繁变化的数据,如 /var/log (日志文件), /var/tmp (比 /tmp 更持久的临时文件)。
  • /tmp (临时文件)
    • 所有用户都可以写入的临时文件,通常在系统重启后会被清空。
  • /usr (Unix System Resources)
    • 包含大部分用户使用的程序和文件,通常是只读的共享数据,如 /usr/bin (大部分用户命令), /usr/lib (库文件)。
    • /usr/local: 本地安装的软件和数据,避免与系统自带的软件包冲突。
    • /usr/share: 与架构无关的共享数据,如文档、man 手册。
  • /opt (可选的应用程序软件包)
    • 用于安装附加的、独立的第三方应用程序软件包。
  • /home (用户主目录)
    • 所有普通用户的个人主目录,包含用户数据和配置文件。
  • /root (超级用户主目录)
    • root 用户(超级用户)的专用主目录。
  • /boot (引导加载程序文件)
    • 引导加载程序(如 GRUB)所需的文件以及 Linux 内核文件,如 /boot/vmlinuz
  • /mnt (临时挂载点)
    • 用于临时挂载文件系统,如 CD/DVD-ROM, USB 驱动器。
  • /media (可移动媒体设备挂载点)
    • 用于自动挂载可移动媒体设备,如 USB 闪存驱动器。
  • /srv (服务数据)
    • 包含特定服务的数据,如 /srv/www (Web 服务器数据)。

2. Linux 内核交互接口:VFS、/proc/sys 与相关核心机制

为了实现用户空间和内核空间的安全高效交互,Linux 内核设计了一系列接口和机制,其中 虚拟文件系统 (VFS) 扮演核心角色,而 /proc/sys 则是其重要实现。

2.1 虚拟文件系统机制(VFS)

VFS (Virtual Filesystem Switch) 是 Linux 内核的一个抽象层,它提供一个 统一的文件系统接口,让用户程序以相同方式访问不同类型的文件系统,屏蔽了底层文件系统的实现细节。

  • 统一接口: 应用程序通过标准系统调用(open(), read(), write(), close())与 VFS 交互。
  • 兼容性: 新的文件系统类型可轻松集成,无需修改现有应用程序。

2.2 虚拟文件系统类型详解

2.2.1 procfs (/proc)

procfs/proc 目录背后的虚拟文件系统,它是一个基于内存的、动态的、大部分只读的文件系统,用于提供关于 系统进程和内核状态的实时信息

  • 进程信息: 每个运行中的进程都有一个以其 PID 命名的子目录(如 /proc/1234),包含 cmdline, exe, status 等。
  • 内核参数与状态: 通过 /proc/sys 子目录暴露大量可读可写的内核参数,允许运行时调整内核行为。
  • 虚拟化: 内容在内存中动态生成,不占用实际磁盘空间。

2.2.2 sysfs (/sys)

sysfs/sys 目录背后的虚拟文件系统,在 Linux 2.6+ 内核中引入,旨在提供一个 更结构化、面向对象、易于编程的接口,用于暴露 内核的设备模型信息

  • 统一设备模型: 它是 Linux 设备模型的具体体现,将设备、驱动、总线等组织成层次化结构。
  • 层次化结构: /sys/bus/ (总线类型), /sys/class/ (设备类别), /sys/devices/ (物理连接拓扑)。
  • 设备属性: 每个设备目录下文件代表设备属性,可读写(如 MAC 地址、电源状态)。
  • 事件通知:udev 紧密协作,通过 netlink 向用户空间发送设备状态变化通知。

2.2.3 tmpfs

tmpfs 是一种基于 RAM(内存)或 Swap(交换空间) 的虚拟文件系统,提供一个 高速、易失性的存储区域

  • 内存存储: 文件和目录存储在 RAM 中,读写速度快。
  • 使用 Swap 空间: RAM 不足时,数据可交换到 Swap 分区。
  • 易失性: 数据在系统重启后全部丢失。
  • 动态调整大小: 根据需要动态增长和收缩。
  • 常见挂载点: /dev/shm (进程间通信), /run (运行时数据), /tmp (临时文件)。

2.2.4 devtmpfs

devtmpfstmpfs 的特殊变种,在 Linux 2.6.32+ 内核中引入,旨在 简化 /dev 目录的生成和管理

  • 动态设备节点: 内核在系统启动早期直接在内存中创建 /dev 下的所有设备文件。
  • 内核直接控制: 确保设备文件在引导早期就可用。
  • udev 协作: devtmpfs 创建基本设备文件,udev 在此基础上提供更高级的命名、权限和自动化管理(如创建符号链接)。
  • 内存存储,易失性: 数据在系统重启后清空。

2.3 相关核心机制

2.3.1 udev 机制

udev 是 Linux 中的 设备管理子系统

  • 动态设备节点创建: 当硬件插入或移除时,动态在 /dev 下创建/删除设备文件。
  • 基于规则的设备配置: 根据 /etc/udev/rules.d/ 中的规则,为设备文件分配固定名称、设置权限,并触发脚本。
  • 用户空间守护进程: 监听内核发出的 netlink 事件。
  • udevadm 命令: 用于查询 udev 状态、测试规则、触发事件(如 udevadm info, udevadm monitor)。

2.3.2 sysctl 机制

sysctl 是命令行工具,用于在运行时 检查和修改 /proc/sys 目录下暴露的内核参数

  • 查询参数: sysctl -a
  • 设置参数: sysctl -w net.ipv4.ip_forward=1
  • 永久设置: 将配置写入 /etc/sysctl.conf/etc/sysctl.d/,然后用 sysctl -p 加载。

2.3.3 kmod 机制

kmod 是用于 管理 Linux 内核模块的工具集。内核模块可在运行时动态加载/卸载,扩展内核功能。

  • modprobe 最常用,加载/卸载模块及其依赖项。
  • insmod 直接加载单个模块文件。
  • rmmod 卸载单个模块。
  • lsmod 列出已加载模块。
  • depmod 分析模块依赖关系。

3. Linux 启动过程深度解析:UEFI → GRUB2 → initramfs → systemd

Linux 系统的启动是一个多阶段协同工作的复杂过程。

3.1 UEFI/BIOS 阶段 (固件初始化)

系统启动的第一个环节,由主板固件负责。现代系统主要使用 UEFI

  • 初始化硬件: 执行 **POST (Power-On Self-Test)**。
  • 启动设备选择: 根据启动顺序查找可引导设备。
  • UEFI 独有特性:
    • 支持 GPT 分区。
    • **安全启动 (Secure Boot)**:验证启动链中组件的数字签名。
    • **EFI 系统分区 (ESP)**:存放 EFI 应用程序(如引导加载器 grubx64.efi)。
  • 流程: UEFI/BIOS 执行 POST → 找到并加载 ESP 中的 EFI 应用程序。

3.2 GRUB2 阶段 (引导加载器)

GRUB2 (GRand Unified Bootloader version 2) 是最常用的引导加载器。

  • 多系统引导: 可识别和引导多个操作系统。
  • 模块化设计: 灵活且强大。
  • 支持多种文件系统: 可直接读取文件系统上的内核和 initramfs
  • 交互式菜单: 提供选择操作系统或修改启动参数的菜单。
  • 流程 (UEFI): UEFI 执行 grubx64.efi → GRUB2 读取 grub.cfg → 加载 Linux 内核映像 (vmlinuz)初始内存文件系统 (initramfs) 到内存 → 将控制权交给内核。

3.3 initramfs (Initial RAM Filesystem) 阶段

在内核挂载根文件系统前,提供临时工具和驱动。

  • 临时根文件系统: 压缩的 CPIO 归档文件,加载到内存中作为临时根文件系统。
  • 提供早期驱动: 包含访问根文件系统所需驱动(如 LVM, 加密文件系统)和早期启动工具。
  • 解压并挂载真根: initramfs 中的 /init 脚本负责加载驱动,找到并挂载真正的根文件系统,然后通过 pivot_rootchroot 切换控制权。

3.4 systemd 阶段 (系统初始化)

控制权最终移交给 /sbin/init,在现代 Linux 中通常是 systemd

  • PID 1 进程: systemd 是系统启动的第一个用户空间进程,PID 永远是 1。
  • 服务管理器: 负责启动、停止、重启、监控所有系统服务。
  • 并行启动: 采用并行化策略,大大加快启动速度。
  • 基于 Unit 的配置: 使用 service, target, mount 等 Unit 文件定义资源和启动行为。
  • 日志管理 (journald): 统一的日志管理机制。
  • 设备管理 (udev): 集成 udev 进行动态设备管理。
  • 流程: 内核启动 systemd → systemd 加载 Unit 文件 → 确定启动目标 → 解析依赖并并行启动服务 → 启动登录管理器 → 用户登录。

3.5 总结流程图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
上电 (按下电源键)
|
V
+-------------------+
| UEFI/BIOS 固件 | (初始化硬件,POST,选择启动设备)
+-------------------+
|
V
+-------------------+
| GRUB2 (引导加载器)| (加载内核和 initramfs 到内存)
+-------------------+
|
V
+-------------------+
| Linux 内核 + | (解压 initramfs, 临时根文件系统,加载驱动,找到并挂载真根)
| initramfs |
+-------------------+
|
V
+-------------------+
| systemd (PID 1) | (加载 Unit,并行启动服务,管理系统进程和资源)
+-------------------+
|
V
用户登录界面 / 系统就绪