Arch Wiki学习笔记

发布于 作者: Ethan

前言

对于Arch Linux Wiki的阅读学习内容记录。

Boot流程

当按下计算机的电源按钮后,屏幕亮起,随后出现操作系统界面——这看似短暂的几秒钟内,计算机内部其实经历了一场复杂且精密的“接力赛”。这份笔记将以 Arch Linux 的引导过程为例,面向零基础读者,将每一个晦涩的技术术语拆解开来,详细解析计算机是如何一步步“醒来”并启动操作系统的。


1. 什么是固件(Firmware)及其类型

固件(Firmware) 是计算机通电后执行的第一个软件程序。它通常被固化在主板上的特殊存储芯片(如闪存)中,独立于我们平时使用的硬盘存储。固件的任务是唤醒硬件,并寻找可以启动的操作系统。目前主流的固件类型分为两代:传统的 BIOS 和现代的 UEFI

1.1 现代标准:UEFI(统一可扩展固件接口)

UEFI 是现代计算机普遍采用的固件标准,用于取代老旧的 BIOS。它拥有诸多先进的特性:

  • 读取文件系统:UEFI 可以直接理解某些“文件系统”(即硬盘上组织和存储数据的方式,例如 FAT12、FAT16、FAT32)。这意味着 UEFI 能够像我们在操作系统中打开文件夹一样,直接读取硬盘上的启动文件。
  • NVRAM(非易失性随机存取存储器):主板上的一块小内存,即使断电也能保存数据。UEFI 依赖 NVRAM 中记录的“启动条目”(Boot Entries)来决定去哪里寻找启动程序。
  • EFI 系统分区(ESP):硬盘上一个专门划分出来的独立区域。各大操作系统(如 Windows、Linux)可以将自己的启动文件(EFI 应用程序)放在这个分区的专属文件夹下(例如 /EFI/厂商名称/),互不干扰。
  • CSM(兼容性支持模块):为了照顾老旧的系统,UEFI 提供了一个叫做 CSM 的功能,它可以模拟传统 BIOS 的工作方式。不过,随着技术的发展,CSM 正逐渐被业界淘汰。

1.2 传统标准:BIOS(基本输入输出系统)

BIOS 是诞生于 IBM PC 时代的老旧固件标准。它受限于早期的技术,无法像 UEFI 那样直接读取复杂的文件系统或分区,而是采用一种非常机械的方式:直接去读取硬盘最开头的几个物理位置(即下文会提到的 MBR),从中强行提取启动代码。


2. 系统初始化阶段(System Initialization)

计算机通电后,固件首先会执行 POST(加电自检,Power-On Self-Test)。这是一个硬件体检过程,用于检查内存、CPU、键盘控制器等基础硬件是否正常运作。体检通过后,不同固件的初始化路线开始分道扬镳。

2.1 UEFI 的启动路径

  1. 硬件初始化:POST 结束后,UEFI 初始化启动所需的硬件(如磁盘驱动器)。
  2. 查找启动条目:UEFI 读取主板 NVRAM 中的启动条目,确定要从哪个磁盘的哪个分区启动哪个文件。
  3. 备用启动路径:如果只有一个空白磁盘而没有明确的启动条目,UEFI 会在这个磁盘上寻找 EFI 系统分区(ESP),并尝试运行默认路径下的文件(通常是 \EFI\BOOT\BOOTx64.EFI)。这就是为什么我们可以通过插入 U 盘来启动安装程序的原因。
  4. 安全启动(Secure Boot):如果开启了此功能,UEFI 会检查启动文件是否带有受信任的数字签名,以防止恶意软件篡改启动过程。
  5. 多启动优势:在 UEFI 下实现多系统(如 Windows 和 Linux 双系统)非常简单。因为不同操作系统的启动文件都和平共处在同一个 EFI 分区中,UEFI 只需要加载对应操作系统的启动程序即可。

2.2 BIOS 的启动路径

  1. 读取 MBR(主引导记录):BIOS 不懂文件系统,它只会按照设定好的磁盘顺序,去读取第一块硬盘最开头的 440 个字节。这个区域被称为 MBR(主引导记录)的代码区。
  2. 第一阶段与第二阶段:因为 440 字节太小了,装不下完整的启动程序,所以这里的代码(第一阶段)通常只起一个“跳板”的作用。它会指示计算机去读取硬盘上的下一个位置(所谓的 post-MBR 间隙)或者某个分区开头的 VBR(卷引导记录),那里存放着更大、更完整的启动代码(第二阶段)。

3. 启动加载器(Bootloader)

启动加载器(Bootloader) 是由固件唤醒的一段软件。它的唯一使命是:把操作系统的核心(内核)以及必要的辅助文件从硬盘搬到内存中,并将其运行起来。 有时我们也会提到 启动管理器(Boot Manager),它主要负责提供一个可视化的菜单,让用户选择要启动哪个系统或工具,选择完毕后再将控制权交给具体的启动加载器。

核心挑战:堆叠块设备与文件系统

现代操作系统的硬盘结构往往非常复杂。比如使用了 LVM(逻辑卷管理器,一种可以灵活调整大小的分区技术)RAID(磁盘阵列,将多个硬盘组合成一个)LUKS(磁盘加密技术)。 如果启动加载器想要找到操作系统内核,它就必须具备“解密”、“组合阵列”、“理解复杂文件系统”的能力。因为极少有启动加载器能够精通所有这些技术,所以 Linux 社区通常推荐创建一个单独的、格式简单的 /boot 分区(例如使用广泛支持的 FAT32 格式),专门用来存放启动所需的核心文件。

常见启动加载器功能对比

Linux 生态中有多种启动加载器,它们各有千秋:

  • GRUB:历史最悠久、功能最强大的启动加载器。支持 BIOS 和 UEFI,支持几乎所有分区表(MBR/GPT)和文件系统,甚至内置了对 LVM 和加密磁盘的有限支持。
  • systemd-boot:一个轻量级的纯 UEFI 启动管理器。配置极其简单,但它只能启动与自己处于同一个分区(或特定扩展分区)内的文件。
  • rEFInd:一个视觉效果极佳的 UEFI 启动管理器,能够自动检测硬盘上的操作系统并生成菜单,支持通过加载驱动来读取多种文件系统。
  • EFI 启动桩(EFI Boot Stub):这是 Linux 内核的一项特殊功能。它允许 Linux 内核伪装成一个普通的 EFI 应用程序。这意味着 UEFI 固件可以直接启动 Linux 内核,完全不需要第三方启动加载器(但这不利于在开机时灵活修改内核参数)。
  • 统一内核镜像(UKI, Unified Kernel Image):将内核、辅助文件(initramfs)和启动参数全部打包成一个单一的 EFI 文件,直接交由 UEFI 启动。
  • Syslinux / Limine / Clover:其他各具特色的启动加载器,适用于不同的特定场景(如制作系统修复 U 盘、模拟 UEFI 环境等)。 (注:像 GRUB Legacy 和 LILO 这样早期的启动加载器由于无法适应现代复杂的磁盘和加密技术,已被时代淘汰。)

4. 操作系统核心:内核(Kernel)

经过启动加载器的努力,内核(Kernel) 终于被载入内存并开始执行。 内核是操作系统的“大脑”和最高统治者。它运行在具有最高权限的底层环境(内核空间,Kernelspace)中,负责与 CPU、内存、显卡等所有硬件直接沟通。 启动后,内核首先会盘点和初始化计算机的所有硬件资源,搭建好舞台,然后准备将控制权逐步移交给为用户服务的普通程序(即用户空间,Userspace)。


5. 初始内存文件系统(initramfs)与早期用户空间

这里存在一个经典的“鸡和蛋”悖论: 内核需要从硬盘上读取操作系统的其他部分。但是,为了读取硬盘,内核又必须先加载对应的硬盘驱动程序。如果这些驱动程序存放在硬盘上,内核该怎么拿到它们呢?

initramfs(Initial RAM File System,初始 RAM 文件系统) 就是为了解决这个问题而诞生的。

5.1 initramfs 是什么?

它是一个被压缩的文件包(通常使用 cpio 归档格式,类似于 ZIP 或 RAR 包)。启动加载器在把内核装入内存的同时,也会把这个 initramfs 包一起塞进内存。 内核启动后,会在内存中开辟一块虚拟的硬盘空间(称为 临时根文件系统),并将 initramfs 解压缩到里面。因为这一切都在内存中发生,内核完全不需要任何物理硬盘的驱动就能访问里面的文件。

5.2 早期用户空间(Early Userspace)的任务

解压后,内核会运行 initramfs 中的一个叫 /init 的程序,从而进入“早期用户空间”阶段。这里的核心任务就是为挂载真正的硬盘做准备:

  1. 加载驱动模块:加载读取物理硬盘所需的内核模块(如 NVMe 固态驱动、USB 驱动等)。
  2. 解密与组装存储栈:如果硬盘被加密(dm-crypt)或使用了逻辑卷(LVM),相关的解密和组装工具会在此时运行,将破碎或锁定的物理磁盘拼凑成一个可用的逻辑磁盘。
  3. 设备解析:通过 udev(Linux 的设备管理器)识别硬件,并给硬盘分配正确的名称。
  4. CPU 微码与 ACPI 更新:在极早的阶段(甚至在解压常规 initramfs 之前),加载来自 CPU 厂商(Intel/AMD)的微指令修复补丁,以修复硬件层面的底层漏洞。

一切准备就绪后,真正的硬盘终于被成功读取并挂载。系统会执行一个称为 switch_root(切换根)的操作,将舞台从内存中的临时系统,正式切换到物理硬盘上的真实操作系统目录中。

5.3 可以不使用 initramfs 吗?

答案是可以的,但这属于高级且受限的玩法。 如果在编译 Linux 内核时,直接将硬盘的驱动程序(如 Ext4 或 Btrfs 文件系统驱动、SATA 驱动)全部“焊死”集成在内核内部(而不是作为外部模块),那么内核就不需要 initramfs 这个“中介”,可以直接去读取物理硬盘。 然而,这种做法不支持复杂的存储技术(如 LVM 或磁盘加密,因为这些技术需要运行额外的用户空间解密程序),且无法使用某些现代的自动挂载功能。


6. 后期用户空间(Late Userspace)与登录

当根目录成功切换到真正的物理硬盘后,系统进入“后期用户空间”阶段。此时,位于真实硬盘上的首个系统程序——初始化系统(如 systemd 或传统的 sysvinit) 开始运行。它是所有其他进程的“祖先”(其进程编号 PID 永远为 1)。

初始化系统会启动网络服务、音频服务、系统日志等各种后台程序。对于普通用户的交互,流程如下:

6.1 终端与 getty

系统通常会初始化几个不可见的纯文本虚拟屏幕(称为虚拟终端,Virtual Terminal)。初始化系统会在这些终端上运行一个叫做 getty 的程序。getty 的作用是保护系统,防止未授权访问。它会在屏幕上打印出 login: 提示符,等待用户输入。

6.2 身份验证(Login)

当输入用户名和密码后,getty 会将信息传递给 login 程序。login 会去系统核心密码本(如 /etc/passwd/etc/shadow)中核对。如果密码正确,login 还会展示当天的问候语或系统通知(MOTD)。

6.3 命令行外壳(Shell)

验证成功后,系统会为用户启动一个 Shell(命令行解释器,如 Bash 或 Zsh)。此时,屏幕上会出现一个命令提示符(例如 [user@archlinux ~]$),用户可以通过输入文本命令来操控计算机了。

6.4 图形化桌面(Display Manager & Xorg/Wayland)

如果系统配置了图形界面,过程会有所不同: 初始化系统不会启动纯文本的 getty,而是启动一个 显示管理器(Display Manager)。这提供了一个美观的图形化登录窗口。 登录成功后,系统会启动 图形显示服务器(Xorg 或更现代的 Wayland),并运行相应的桌面环境(如 KDE、GNOME)。至此,熟悉的鼠标指针和应用窗口终于呈现在屏幕上,漫长而精密的引导过程圆满结束,计算机完全准备好响应用户的每一次点击。

UEFI(统一可扩展固件接口)

当计算机接通电源时,在屏幕显示出熟悉的操作系统(如 Windows 或 Linux)之前,硬件需要一套初始程序来“唤醒”并指挥它们。UEFI(Unified Extensible Firmware Interface,统一可扩展固件接口) 就是目前最主流的这类底层程序标准。本篇笔记将基于专业文档,为零基础读者全面解析 UEFI 的核心概念、工作机制以及相关的配置与故障排查技术。


1. 基础概念解析

在深入具体操作之前,有必要先厘清以下几个核心术语:

  • 固件(Firmware):固化在计算机主板硬件芯片中的基础软件。它是计算机通电后执行的第一段代码。
  • BIOS 与 MBR:BIOS(基本输入输出系统)是早期计算机的固件标准。它通过读取硬盘最开头的物理扇区(即 MBR,主引导记录)来寻找启动代码。这种方式受限于早期技术,难以支持大容量硬盘和复杂的文件系统。
  • UEFI:新一代的固件标准,旨在取代老旧的 BIOS。UEFI 能够直接识别硬盘上的文件系统(如 FAT32),并从一个专门的硬盘分区(称为 ESP,EFI 系统分区)中直接读取启动文件(EFI 应用程序)。
  • 架构位数(Bitness):计算机处理数据的通道宽度,常见的有 32 位(IA32)和 64 位(x64)。这决定了系统一次能处理多少信息。

2. UEFI 固件的架构位数

在 UEFI 环境下,所有的操作系统加载器(启动程序)或系统工具,都必须是一类特定的文件——EFI 应用程序(.efi 文件)。这些应用程序的架构位数必须与主板上 UEFI 固件的位数完全匹配。

目前绝大多数现代计算机(包括近年的苹果 Mac)都采用 x64(64 位) UEFI 固件。只有极少数设备(如 2008 年前的旧款 Mac、早期的 Intel Atom 处理器设备)使用 IA32(32 位) UEFI 固件。需要特别注意的是,64 位的 UEFI 固件无法运行 32 位的 EFI 应用程序。如果设备采用的是 32 位 UEFI,但需要安装 64 位的操作系统,则必须使用支持“混合模式启动”的特殊启动加载器。

2.1 如何检查固件位数

操作者可以在已启动的操作系统中检查当前主板固件的位数:

  • 在 Linux 中: 对于内核版本 4.0 及以上的系统,通过读取系统内部信息接口来确认。可以执行命令: cat /sys/firmware/efi/fw_platform_size 如果输出 64,代表 64 位(x64)UEFI;输出 32 代表 32 位(IA32)UEFI。如果提示文件不存在,说明当前系统不是通过 UEFI 模式启动的(可能是通过传统的 BIOS 模式启动)。
  • 在 macOS 中: 在终端中输入: ioreg -l -p IODeviceTree | grep firmware-abi 返回 EFI64 为 64 位,EFI32 为 32 位。(注:苹果的 EFI 实现并不完全符合标准的 UEFI 规范)。
  • 在 Windows 中: 因为 64 位 Windows 强制要求 64 位 UEFI 才能启动,所以可以直接运行系统信息工具 msinfo32.exe。查看“系统摘要”中的“系统类型”(若为 x64-based PC)和“BIOS 模式”(若为 UEFI),即可确认。

3. UEFI 变量(UEFI Variables)

UEFI 变量 是操作系统与底层固件进行沟通的“备忘录”。它们通常存储在主板的 NVRAM(非易失性随机存取存储器,一种断电后数据不会丢失的存储芯片) 中。这些变量记录了计算机的启动顺序、安全启动的密钥以及其他底层硬件设置。

3.1 Linux 对 UEFI 变量的支持

Linux 系统通过一种名为 efivarfs(EFI 变量文件系统)的机制,将这些底层硬件数据“翻译”成普通的系统文件,挂载到(即链接到)/sys/firmware/efi/efivars 目录下,以便让上层的软件能够读取和修改它们。

实现这一功能的前提条件:

  1. 系统必须是以纯正的 UEFI 模式启动,不能使用 CSM(兼容性支持模块,即 UEFI 模拟的老旧 BIOS 模式)。
  2. Linux 内核必须开启了 EFI 运行时服务(EFI Runtime Services)的支持。
  3. 系统启动参数中没有禁用 EFI 功能(即不能带有 noefi 参数)。

如果启动后发现上述目录没有自动生成,操作者需要手动进行挂载(映射)操作: mount -t efivarfs efivarfs /sys/firmware/efi/efivars

3.2 管理 UEFI 变量的工具

在 Linux 中,有多种专门的工具用于管理这些变量:

  • efivar:用于底层操作变量的库和命令行工具。
  • efibootmgr:最常用的工具,专门用于管理 UEFI 固件的启动菜单(如调整启动顺序、添加或删除启动项)。
  • efitools:用于管理 UEFI 安全启动平台相关设置。
  • QEFI Entry Manager:带有图形界面的启动项管理软件。

3.3 使用 efibootmgr 管理启动项

假设需要手动在主板的启动菜单中添加一个名为 "rEFInd Boot Manager" 的新系统,需要知道三个信息:EFI 分区所在的硬盘(如 /dev/sda)、分区编号(如 1)、以及该程序在分区内的路径。 创建新启动项的命令如下: efibootmgr --create --disk /dev/sda --part 1 --loader '\EFI\refind\refind_x64.efi' --label 'rEFInd Boot Manager' --unicode

  • 查看当前的启动菜单顺序:efibootmgr --unicode
  • 修改启动顺序(XXXX为启动项的编号):efibootmgr --bootorder XXXX,XXXX --unicode
  • 删除特定的启动项:efibootmgr --delete-bootnum --bootnum XXXX --unicode

3.4 禁用 UEFI 变量访问的安全考量

由于 UEFI 拥有极高的硬件权限,恶意软件如果篡改了 UEFI 变量,可能会彻底控制计算机,甚至导致硬件级死机(例如 LogoFAIL 漏洞)。如果在日常使用中不需要修改启动项,出于安全考虑,可以将 efivarfs 设置为只读(Read-Only) 模式,或者在启动参数中加入 noefi 来彻底切断操作系统对固件的访问权限。


4. UEFI Shell(命令行环境)

UEFI Shell 是固件自带的一个类似于 DOS 或 Linux 终端的纯文本命令行界面。在没有进入任何操作系统之前,它允许操作者直接执行底层的 EFI 应用程序。

4.1 获取与启动 UEFI Shell

根据主板固件规范的新旧,UEFI Shell 分为 v1 和 v2 两个主要版本。现代系统推荐使用 v2 版本(可以从 TianoCore EDK2 项目获取)。 许多主板(如华硕的 Aptio 固件)提供了“从文件系统设备启动 EFI Shell”的选项。操作者只需将 Shell 的执行文件命名为 shellx64.efi,并放入 ESP 分区的根目录即可。如果主板没有该选项,可以将其放在一个 FAT32 格式 U 盘的 \EFI\BOOT\BOOTx64.EFI 路径下,从而伪装成一个默认的可启动 U 盘来运行。

4.2 核心 Shell 命令

在 UEFI Shell 中,可以通过在命令后加上 -b 参数来实现分页显示(防止文字滚动过快)。

  • bcfg:这是一个极其强大的命令,用于直接修改 NVRAM 中的启动条目。当 Linux 下的 efibootmgr 工具失效时,可以直接在 Shell 中使用此命令。例如,将某程序添加为第 4 个启动选项: bcfg boot add 3 FS0:\EFI\refind\refind_x64.efi "rEFInd Boot Manager"
  • map:列出当前所有可用的存储设备和文件系统映射(类似于 Windows 中的 C盘、D盘,在此处显示为 FS0:FS1: 等)。
  • edit:一个基础的纯文本编辑器,支持 UTF-8 编码,可以直接在底层修改配置文件(如 edit FS0:\EFI\refind\refind.conf)。

5. UEFI 驱动程序(UEFI Drivers)

标准 UEFI 固件通常只能识别 FAT 类格式的文件系统。如果想要在 UEFI 阶段直接读取如 NTFS(Windows 常用)格式的硬盘,就需要加载UEFI 驱动程序。 驱动程序也是一种特殊的软件,用于赋予系统原本不具备的能力。在 UEFI Shell 中,可以通过 load 命令加载特定的驱动(例如 load ntfs_x64.efi),然后再执行 map -r 刷新设备列表。完成后,系统便能识别并浏览 NTFS 格式的分区了。一些高级的启动管理器(如 rEFInd 或 systemd-boot)支持在启动时自动静默加载这些驱动。


6. UEFI 可引导媒体与测试

6.1 移除光盘的 UEFI 支持

对于某些特定环境(如老旧的 32 位 EFI Mac 电脑),它们会拒绝从同时支持 UEFI 和传统 BIOS 的混合启动光盘(CD/DVD)启动。此时,需要使用特定工具(如 bsdtarxorriso)提取官方 ISO 镜像的内容,剔除其中与 UEFI 相关的目录(如 /EFI/),然后重新打包生成一个纯 BIOS 引导的光盘镜像,以便强行以传统模式安装系统。

6.2 在无原生支持的系统上测试 UEFI

开发人员或用户如果想在虚拟机中测试 UEFI 启动,可以使用 OVMF(Open Virtual Machine Firmware)。这是一个为虚拟机(如 QEMU)提供 UEFI 环境的开源项目。通过为虚拟机指定 OVMF 的代码文件和专用的变量存储文件,即可在虚拟机内部模拟出真实的 UEFI 启动过程。


7. 常见故障排查(Troubleshooting)

引导层面的故障通常会导致计算机无法启动或进入错误的系统。以下是常见的疑难解答:

  • 双系统卡在 Windows 无法进入 Linux: 如果在 Windows 中无法切换回 Linux,可以通过 Windows 的“高级启动”功能强制重启进入固件菜单:在设置中选择“恢复 -> 高级启动 -> 立即重启”,然后在菜单中选择“使用设备”,从中找到 Linux 的启动项。
  • 无法通过键盘快捷键进入主板设置: 部分笔记本(如联想某些型号)由于硬件设置问题,开机狂按 F2 或 F12 毫无反应。可以在 Linux 终端中输入 systemctl reboot --firmware-setup,或者在 GRUB 启动器命令行中输入 fwsetup,系统在下一次重启时会自动强制进入主板 UEFI 设置界面。
  • Windows 强行更改启动顺序: 在某些主板上,只要检测到 Windows 的存在,主板会自动无视 Linux 设定的启动顺序,强行将 Windows 置于首位。针对此“流氓”行为的对策有:
    1. 确保 Windows 中的“快速启动(Fast Startup)”已关闭。
    2. 在 Windows 中以管理员身份运行命令,将默认启动器路径强行修改为 Linux 的引导程序:bcdedit /set "{bootmgr}" path "\EFI\path\to\app.efi"
    3. 利用 Windows 任务计划程序,设置一个开机脚本,每次 Windows 启动时自动将控制权交还给 Linux 的启动标识。
  • 启动项无故消失(NVRAM 维护机制): 有些主板为了防止 NVRAM 空间不足,或者出于所谓的“维护目的”,在开机时会检查启动项指向的文件是否存在。如果主板只认特定的路径(例如某些 Intel 主板只认 Windows 的路径),它可能会清空所有非 Windows 的启动项。 终极解决方案(默认安全路径机制):UEFI 规范定义了一个“万能备用路径”:/EFI/BOOT/BOOTx64.EFI。绝大多数主板在找不到任何已知启动项时,都会尝试启动这个固定路径下的文件。将 Linux 的引导程序复制并重命名存放到该路径下,或者在该路径下创建一个空文件“欺骗”主板,可以有效防止启动项被意外抹除。
  • 联想 ThinkPad 的特殊情况: 近代部分 ThinkPad 笔记本中有一项名为 OS Optimized Defaults(操作系统优化默认值)的设置。该功能会在每次重启时重置所有 UEFI 变量以迎合 Windows。必须在 BIOS 中彻底关闭此选项,手动创建的 Linux 启动项才能永久保存。

开机自检 (POST)

开机自检(Power-On Self-Test,简称 POST)是计算机以及其他包含微处理器的电子设备在接通电源后,由基本输入输出系统(BIOS)或统一可扩展固件接口(UEFI)自动执行的一系列初始诊断测试过程。其核心目的是在加载操作系统之前,验证系统的关键硬件组件是否齐备且运行正常。

1. POST 的核心工作流程

当计算机接通电源并稳定电压后,主板会向中央处理器(CPU)发送一个复位信号,唤醒 CPU。随后,CPU 会定向读取主板固化芯片中的 BIOS/UEFI 代码,正式触发 POST 过程。这一自检过程通常按严格的顺序执行,包含以下关键步骤:

  • 处理器与主板通信测试:首先验证 CPU 本身的基本功能、主板芯片组以及系统总线之间的指令传输通道是否正常。
  • 内存(RAM)检测:系统会快速向内存条写入并读取数据,以核对内存的物理容量,并确认内存模块的读写功能不存在硬件级短路或故障。
  • 显卡初始化:查找并检测显卡(集成显卡或独立显卡),加载基础视频固件。这一步完成后,计算机才具备在显示器上输出画面或可视错误信息的能力。
  • 存储与外部设备轮询:检测键盘、鼠标等基本输入设备,并识别连接到主板接口(如 SATA、M.2、USB)的硬盘、固态硬盘(SSD)等存储驱动器,寻找可引导的操作系统。

2. POST 的错误反馈机制

如果在自检的任何一个环节中发现致命的硬件级故障(例如未插内存条、显卡损坏或 CPU 异常),POST 将立即中止,引导过程也会随之停滞。为了帮助排查硬件问题,系统会通过以下几种机制发出诊断警报:

  • 蜂鸣器报警代码(Beep Codes):在显卡尚未初始化或显示器无法点亮时,主板附带的蜂鸣器会发出特定节奏的音频信号。不同主板厂商拥有不同的报警规则,例如连续的短音可能代表电源故障,而“一长两短”往往指向显卡异常。
  • 十六进制诊断码(Q-Code):现代高级主板通常配备了专用的 LED 调试指示灯。在启动时,该指示灯会快速滚动显示两位数的十六进制代码。如果系统卡死,最终停留的代码即可用于对照主板手册,精准定位故障硬件。
  • 屏幕错误信息:如果显卡已成功自检并工作,但其他非致命组件(如键盘未连接或系统风扇转速异常)出现问题,屏幕上会直接输出文本错误提示,例如 “Keyboard error or no keyboard present” 或 “CPU Fan Error”。

3. POST 的系统学意义

POST 是建立计算机运行信任链的第一道防线。它通过纯硬件层面的底层检测,阻止了带有严重物理缺陷的设备强行读写数据,从而避免了潜在的数据损坏或硬件烧毁风险。一旦 POST 顺利通过,系统通常会发出一声清脆的短促蜂鸣声(即“自检通过”提示音),随后 BIOS/UEFI 会将计算机的控制权正式移交给引导加载程序(Bootloader),开始将操作系统载入内存。

网络接口

1 网络接口概述

网络接口由 udev 进行管理,并通过 systemd.link(5) 文件进行配置。系统默认的配置会使用“可预测的网络接口名称(Predictable Network Interface Names)”为网络接口控制器分配名称。这些名称通常带有特定的前缀:

  • en:用于有线网络或以太网(Wired/Ethernet)。
  • wl:用于无线网络(Wireless/WLAN)。
  • ww:用于移动宽带(Mobile broadband/WWAN)。

配置与诊断提示:

  • 系统默认的配置文件路径为 /usr/lib/systemd/network/99-default.link,该文件在大多数情况下已经足够满足常规需求。
  • 如果需要诊断 .link 文件的问题,可以以 root 用户身份运行以下命令: udevadm test-builtin net_setup_link /sys/path/to/network/device
  • 注意:在添加或移除 PCIe 设备后,如果系统固件决定对设备重新编号,可预测的网络接口名称可能会发生变化。此外,安装 iwd 软件包会附带一个禁用可预测命名规则的 .link 文件,仅仅安装该包就会阻止所有网络接口被重命名为可预测名称。

2 列出网络接口

可以通过执行 ls /sys/class/netip link 命令来查看有线和无线接口的名称。

  • lo 接口是虚拟的回环接口(Virtual loopback interface),不用于建立实际的外部网络连接。
  • 针对无线设备,还可以使用 iw dev 命令来获取接口名称。
  • 如果某个网络接口未被列出,通常说明该设备的驱动程序未能成功加载,需要进一步检查驱动状态。

3 启用与禁用网络接口

可以使用 ip link 命令来控制网络接口的启用或禁用状态: ip link set <接口名称> up|down

要检查特定接口(例如 enp2s0)的状态,可以运行: ip link show dev enp2s0 在输出信息的 <BROADCAST,MULTICAST,UP,LOWER_UP> 字段中,如果存在 UP,即表示该接口已启用(即使后续的状态信息显示为 state DOWN)。

路由注意事项: 如果系统的默认路由经过某个特定的接口,将该接口关闭(down)会同时移除该默认路由;重新启用该接口时,默认路由并不会自动恢复,需要手动重新建立路由表。


4 更改网络接口名称

在更改网络接口的命名方案时,必须同步更新所有与网络相关的配置文件以及自定义的 systemd 单元文件,以反映名称的变更。同时,在更改名称之前,必须确保网络接口处于关闭(down)状态。

获取每块网卡 MAC 地址的方法是运行 ip link。注意:在编写规则时,MAC 地址必须使用小写的十六进制值。

4.1 使用 systemd.link 文件

可以通过手动定义 systemd.link(5) 文件来更改设备名称。该文件的命名必须在字典序上优先于 99-default.link,例如创建一个名为 /etc/systemd/network/10-net0.link 的文件:

[Match]
PermanentMACAddress=aa:bb:cc:dd:ee:ff

[Link]
Name=net0

注意:在 systemd.link 配置中,Name 的优先级低于 NamePolicy。因此,必须确保 NamePolicy 未设置或为空,否则名称更改将不会生效。

4.2 使用 udev 规则

也可以通过创建 udev 规则来实现,例如创建 /etc/udev/rules.d/10-network.rules

SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="aa:bb:cc:dd:ee:ff", NAME="net0"

这些规则会在系统启动时自动应用。若要立即生效,可以在 net 子系统上手动触发该 udev 规则: # udevadm trigger --verbose --subsystem-match=net --action=add 如需测试更改,可以使用 udevadm --debug test /sys/class/net/* 命令。

4.3 动态 MAC 地址与 USB 设备的匹配

如果网卡具有动态分配的 MAC 地址(例如通过 Android 手机共享的 USB 网络设备),依赖 MAC 地址匹配将会失效。此时可以使用以下替代方案:

方案 A:通过 Path 匹配(systemd.link) 可以使用 networkctl status <接口名称> 检查设备的路径。

[Match]
Path=pci-0000:01:00.0

[Link]
Name=net1

方案 B:通过 DEVPATH 匹配(udev 规则) 查看 /sys/class/net/ 目录下的符号链接即可获取 DEVPATH

SUBSYSTEM=="net", DEVPATH=="/devices/pci*/*1c.0/*/net/*", NAME="net1"

警告:设备路径的匹配规则必须同时兼容新设备名和旧设备名(因为规则在启动时可能会被执行多次)。如果不兼容,名称可能会被系统默认规则改回原样。

方案 C:通过 Vendor 和 Model ID 匹配 当希望使用不同的 USB 端口时,可以根据供应商 ID 和产品 ID 进行匹配。 通过 systemd.link:

[Match]
Property=ID_VENDOR_ID=12ab ID_MODEL_ID=3cd4

[Link]
Name=net2

通过 udev 规则:

SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="12ab", ATTRS{idProduct}=="3cd4", NAME="net2"

4.4 命名安全约定

选择静态名称时,应避免使用类似 ethXwlanX 的格式。因为内核在默认情况下也会使用此类名称,这可能导致启动期间内核与 udev 之间发生竞态条件。建议使用内核不会默认使用的名称,如 net0net1wifi0wifi1 等。


5 恢复传统接口名称

如果更倾向于使用传统的网络接口名称(如 eth0),可以通过以下三种方式之一禁用“可预测的网络接口名称”功能:

  1. 修改 NamePolicy(推荐): 覆盖 udev 的 net_setup_link 内置默认策略,创建 /etc/systemd/network/99-default.link.d/traditional-naming.conf 并添加:

    [Link]
    NamePolicy=keep kernel
    
  2. 屏蔽 udev 规则: 完全禁用 net_setup_link,通过将相应的 udev 规则链接到黑洞: # ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules

  3. 调整内核参数: 在系统的内核启动参数中追加 net.ifnames=0

备注:由于 systemd.link(5) 依赖于 net_setup_link 运行,除非确切了解屏蔽规则的后果,否则建议优先采用第一种方法(修改 NamePolicy)。


6 设置设备 MTU 与传输队列长度

可以通过 systemd.link(5) 配置文件或 udev 规则来手动修改网络设备的 MTU(最大传输单元)和队列长度。

使用 systemd.link 的示例 (/etc/systemd/network/30-mtu.link):

[Match]
Type=wlan

[Link]
MTUBytes=1500
TransmitQueueLength=2000

(注意:一旦创建类似 30-mtu.link 的文件,若其匹配规则覆盖了全部设备,可能会导致 99-default.link 不再被应用)

使用 udev 规则的示例 (/etc/udev/rules.d/10-network.rules):

ACTION=="add", SUBSYSTEM=="net", KERNEL=="wl*", ATTR{mtu}="1500", ATTR{tx_queue_len}="2000"

参数详解:

  • MTUBytes(最大传输单元):常规默认值为 1500。使用大于 1500 的值(称为巨型帧 / jumbo frames)可以显著加快网络传输速度。但必须确保本地网络中的所有网络接口和交换机都支持相同的 MTU 才能使用巨型帧。对于 PPPoE 连接,MTU 不应大于 1492。该值也可通过 systemd.netdev(5) 设置。
  • TransmitQueueLength(传输队列长度):对于具有高延迟的慢速设备(如调制解调器链路和 ISDN),建议设置较小的值。对于通过高速互联网连接并执行大量数据传输的服务器,建议设置较高的值(如 2000)。

iwd / iwctl

iwd(iNet 无线守护进程,iNet Wireless Daemon)是由英特尔(Intel)编写的 Linux 无线网络守护进程。该项目的核心目标是优化资源利用率,通过不依赖任何外部库、最大限度地利用 Linux 内核提供的功能来实现高效运行。

iwd 既可以在独立模式下工作,也可以与诸如 ConnMan、systemd-networkd 以及 NetworkManager 等全面的网络管理器结合使用。

重要提示: 若在使用其他网络管理器(如 NetworkManager)时将其后端配置为 iwd,除非该网络管理器的相关文档中明确说明,否则不应直接混合使用本指南中的独立配置命令。


安装指南

要开始使用,需安装基础的 iwd 软件包。

为了方便操作,可以选择安装第三方提供的图形界面(GUI)或终端用户界面(TUI)前端工具:

  • impala:一款基于终端用户界面(TUI)的 iwd 前端。
  • iwdgui:一款 iwd 的图形界面前端。
  • iwgtk:一款提供图形界面和状态栏指示器(系统托盘)图标的 iwd 前端。
  • iwmenu:一款菜单驱动的 iwd 交互界面。
  • iwqt:一款适用于 Linux 系统的 iwd 网络小部件。

基础使用说明

iwd 软件包核心包含三个主要组件:客户端程序 iwctl、守护进程 iwd 以及 Wi-Fi 监控工具 iwmon

在使用前,必须启动并启用 iwd.service 系统服务,以便后续通过首选的前端工具或直接使用 iwctl 命令对其进行控制。

权限说明: 仅有 root 用户以及属于 networkwheel 用户组的成员被允许与 iwd 守护进程进行交互。若要以普通用户身份使用 iwctl 或其他前端,需确保该用户已被加入上述相应组中。

iwctl 命令行交互

要进入交互式命令提示符,请在终端执行:

iwctl

进入后,交互式提示符将以 [iwd]# 作为前缀显示。

提示:在 iwctl 提示符中,按下 Tab 键可以自动补全命令、设备名称和 SSID。要退出交互式提示符,可通过按下 Ctrl+d 发送 EOF 信号。

用户也可以在不进入交互式提示符的情况下,直接将所有命令作为命令行参数执行。例如:iwctl device wlan0 show

若要列出所有可用的内置命令,可输入:

[iwd]# help

连接到无线网络

  1. 查找设备: 若需确认系统中的无线设备名称,可列出所有 Wi-Fi 设备:

    [iwd]# device list
    
  2. 启用设备: 若设备或其对应的适配器处于关闭状态,需将其开启(将 nameadapter 替换为实际名称):

    [iwd]# device name set-property Powered on
    [iwd]# adapter adapter set-property Powered on
    
  3. 扫描网络: 启动网络扫描(此命令在执行时不会产生终端输出):

    [iwd]# station name scan
    
  4. 列出网络: 扫描完成后,列出所有可用的网络:

    [iwd]# station name get-networks
    
  5. 发起连接: 连接到指定的 SSID:

    [iwd]# station name connect SSID
    

    对于隐藏网络,请使用以下命令:

    [iwd]# station name connect-hidden SSID
    

注意: 要通过 DHCP 自动获取 IP 和 DNS 配置,必须手动启用 iwd 内置的 DHCP 客户端,或者配置并运行一个独立的 DHCP 客户端程序。

若连接的网络需要输入密码短语(且该密码尚未存储在 iwd 的配置文件中),系统将弹出提示要求输入。用户也可以直接通过命令行参数提供密码:

iwctl --passphrase passphrase station name connect SSID

备注:iwd 会自动将成功连接的网络密码短语加密存储在 /var/lib/iwd 目录中,以便未来实现自动连接。iwd 仅支持长度在 8 到 63 个 ASCII 编码字符之间的 PSK 密码短语。若密码不符合此规范,系统将返回错误 PMK generation failed. Ensure Crypto Engine is properly configured

此外,若目标 SSID 名称中包含空格,在输入连接命令时需将完整的网络名称用双引号括起来。

使用 WPS/WSC 进行连接

若目标网络及路由器支持 Wi-Fi 保护设置(WPS,通过按下物理按钮连接),首先需确认本机的网络设备也支持此功能:

[iwd]# wsc list

若设备出现在上述列表中,可执行以下命令触发连接:

[iwd]# wsc device push-button

随后,需在 2 分钟内按下路由器上的 WPS 按钮以完成握手连接。如果网络要求验证 PIN 码,可通过查阅 help 命令的输出,了解如何向 wsc 命令传递正确的参数。

断开连接与信息查看

  • 断开网络连接:

    [iwd]# station device disconnect
    
  • 显示设备详细信息(例如 MAC 地址等硬件参数):

    [iwd]# device device show
    
  • 显示连接状态(包括当前连接的网络详情):

    [iwd]# station device show
    

管理已知网络

  • 列出历史连接过的已知网络:

    [iwd]# known-networks list
    
  • 忘记/移除指定的已知网络:

    [iwd]# known-networks SSID forget
    

iwgtk 图形化管理

iwgtk 软件包提供了一个直观的图形界面,用于替代命令行控制 iwd。 不带任何参数运行 iwgtk 将启动应用程序主窗口。在该窗口中可以切换适配器和设备的电源状态、更改运行模式、查看可用网络、建立连接以及管理已知网络。

状态指示器图标: 若要启动 iwgtk 的系统托盘指示器守护进程,可运行:

iwgtk -i

若指示器图标未显示,可能是由于系统托盘不支持 StatusNotifierItem API。此时需要运行兼容层工具(如 snixembed-git)。

  • 原生支持该 API 的桌面环境包括:KDE Plasma、swaybar、lxqt-panel、xfce4-panel。
  • 仅支持 XEmbed(需依赖兼容层)的环境包括:AwesomeWM、i3bar、stalonetray。

自动启动设置: 通过 AUR 安装的 iwgtk 软件包通常会将 iwgtk-indicator.desktop 文件放置在 /etc/xdg/autostart/ 目录中,以支持在遵循 XDG 标准的桌面环境中登录时自动启动托盘图标。此外,若桌面环境支持 systemd 的 graphical-session.target,也可以通过启用 iwgtk.service 用户单元来实现自动启动。


网络配置文件详解

默认情况下,iwd 将所有的网络凭据和配置文件存储在 /var/lib/iwd 目录中。 配置文件的命名规则为 network.type,其中 network 代表网络的 SSID,而 .type 代表网络安全类型,可选项包括 .open(开放网络)、.psk(预共享密钥)或 .8021x(企业级认证)。这些文件用于存储加密的预共享密钥(PreSharedKey),也可以包含明文密码(Passphrase)。用户可以手动创建和编辑这些文件,无需依赖 iwctl 自动生成。

文件命名特殊规则: 仅当网络 SSID 全由字母、数字或连字符(-_)组成时,才会直接将其用作文件名。如果 SSID 包含任何其他特殊字符,文件名将被替换为一个 = 字符,后跟该 SSID 的全小写十六进制编码字符串。 字符串转义规则: 在配置文件中定义身份和密码等字符串值时,前导空格、\n\r 以及字面量反斜杠等字符必须进行适当转义。

WPA-PSK 个人网络配置

以下是一个连接到 SSID 为 spaceship 且密码为 test1234 的 WPA/WPA2-PSK 网络的配置示例:

/var/lib/iwd/spaceship.psk

[Security]
PreSharedKey=aafb192ce2da24d8c7805c956136f45dd612103f086034c402ed266355297295

若不想手动计算哈希,可以直接在配置文件中输入明文密码:

[Security]
Passphrase=test1234

在 iwd 首次成功连接后,它会自动计算对应的哈希值,并将 PreSharedKey 字段追加写入该文件中。若需手动生成该密钥,亦可使用 wpa_passphrasewpa-psk 等工具。

WPA 企业级认证 (802.1X) 配置

1. EAP-PWD 认证: 创建名为 essid.8021x 的文件以连接 EAP-PWD 保护的接入点:

/var/lib/iwd/essid.8021x

[Security]
EAP-Method=PWD
EAP-Identity=your_enterprise_email
EAP-Password=your_password

[Settings]
AutoConnect=true

若不希望自动连接,可将 AutoConnect 设为 false 并通过 iwctl 手动触发。出于安全考虑,如果不想在文件中明文保存密码,可直接删除 EAP-Password 字段,iwd 会在连接时提示输入。

2. EAP-PEAP 认证: 此配置常用于教育或企业网络,通常需要 CA 证书配合 MSCHAPv2 认证。

/var/lib/iwd/essid.8021x

[Security]
EAP-Method=PEAP
EAP-Identity=anonymous@realm.edu
EAP-PEAP-CACert=/path/to/root.crt
EAP-PEAP-ServerDomainMask=radius.realm.edu
EAP-PEAP-Phase2-Method=MSCHAPV2
EAP-PEAP-Phase2-Identity=johndoe@realm.edu
EAP-PEAP-Phase2-Password=hunter2

[Settings]
AutoConnect=true

若需存储 MSCHAPv2 密码的哈希值而非明文,可使用以下命令计算 md4 哈希(输入密码后按 Ctrl+D 结束,不要按回车):

iconv -t utf16le | openssl md4 -provider legacy

随后将生成的哈希值填入配置文件的 EAP-PEAP-Phase2-Password-Hash 键中。

3. TTLS-PAP 认证: 类似 PEAP,但使用 PAP 协议:

/var/lib/iwd/essid.8021x

[Security]
EAP-Method=TTLS
EAP-Identity=anonymous@uni-beispiel.de
EAP-TTLS-CACert=cert.pem
EAP-TTLS-ServerDomainMask=*.uni-beispiel.de
EAP-TTLS-Phase2-Method=Tunneled-PAP
EAP-TTLS-Phase2-Identity=user
EAP-TTLS-Phase2-Password=password

[Settings]
AutoConnect=true

4. EAP-TLS 认证: EAP-TLS 使用 x509 客户端证书进行身份验证。这种非对称加密机制无需将敏感密码发送至验证服务器。配置需要根 CA 证书、客户端证书及对应的私钥。

/var/lib/iwd/essid.8021x

[Security]
EAP-Method=TLS
EAP-TLS-CACert=/path/to/cacert.pem
EAP-Identity=your_enterprise_email
EAP-TLS-ClientCert=/path/to/client-cert.pem
EAP-TLS-ClientKey=/path/to/client-key.pem
# 如果客户端私钥已加密,需提供如下密码短语
#EAP-TLS-ClientKeyPassphrase=key-passphrase  

[Settings]
AutoConnect=true

5. Eduroam 网络特殊配置: 对于全球教育漫游网络 eduroam,通常基于 PEAP-MSCHAPV2。可以通过 eduroam 官方提供的配置助手工具 (CAT) 下载 Linux 脚本以提取配置参数。如果网络机构升级到了 EAP-TLS,可能需要使用如 SecureW2 等工具生成客户端证书。CAT 脚本中的变量与 iwd 字段的映射关系大致如下:

  • Config.ssids -> 文件名 (essid)
  • Config.eap_outer -> EAP-Method
  • Config.anonymous_identity -> EAP-Identity
  • Config.CA -> EAP-method-CACert
  • Config.servers -> EAP-method-ServerDomainMask (若以 DNS: 开头,仅保留其后内容)
  • Config.eap_inner -> EAP-method-Phase2-Method (若为 PAP,则使用 Tunneled-PAP)
  • username@Config.user_realm -> EAP-method-Phase2-Identity

6. 内嵌证书配置 (Embedded certificates): iwd 支持直接将 PEM 格式的证书数据内嵌到配置文件中,而非提供绝对路径。格式如下:

[@pem@my_ca_cert]
----- BEGIN CERTIFICATE -----
PEM data
----- END CERTIFICATE -----

在设置中通过 embed: 前缀进行引用:

EAP-TTLS-CACert=embed:my_ca_cert

此方法适用于 CA 证书、客户端证书、私钥以及证书链。

7. 有线以太网上的 WPA: 对于依赖 802.1X 的有线网络连接,需按上述格式创建配置文件,但应将其保存在 /var/lib/ead 目录中。配置完成后,需启动并启用 ead.service 系统服务。


全局与高级选项配置

iwd 的主全局配置文件位于 /etc/iwd/main.conf(如文件不存在需手动创建)。更多详细参数请参阅手册页 iwd.config(5)

禁用特定网络的自动连接

若要阻止 iwd 自动连接某个已知网络,可在其对应的网络配置文件(如 /var/lib/iwd/network.type)中添加:

[Settings]
AutoConnect=false

禁用后台周期性网络扫描

默认情况下,处于断开状态的 iwd 会周期性地扫描可用网络。若需完全依赖手动扫描,可在主配置文件中添加: /etc/iwd/main.conf

[Scan]
DisablePeriodicScan=true

启用内置的网络配置 (DHCP / 静态 IP)

自 0.19 版本起,iwd 具备了使用内置 DHCP 客户端或静态配置分配 IP 地址及设置路由的功能。这可以作为独立 DHCP 客户端的轻量级替代方案。 在主配置文件中启用: /etc/iwd/main.conf

[General]
EnableNetworkConfiguration=true

如需调整路由优先级(Metric),可配置:

[Network]
RoutePriorityOffset=300

IPv6 支持设置

iwd 在 1.10 版本后引入了 IPv6 支持。在 2.0 之前的版本中默认禁用,而在 2.0 及更高版本中默认启用。 如需显式启用或禁用 IPv6 支持,请在主配置文件中设置: /etc/iwd/main.conf

[Network]
EnableIPv6=true # 或设置为 false 以禁用

配置静态 IP 地址

针对特定网络,可以在其网络配置文件(如 /var/lib/iwd/spaceship.psk)中添加静态 IP 设置:

[IPv4]
Address=192.168.1.10
Netmask=255.255.255.0
Gateway=192.168.1.1
Broadcast=192.168.1.255
DNS=192.168.1.1

选择 DNS 解析管理器

iwd 当前支持 systemd-resolvedresolvconf 两种 DNS 管理器。在基于 systemd 的系统中,默认推荐使用 systemd-resolved。 若需显式指定: /etc/iwd/main.conf

[Network]
NameResolvingService=systemd # 或设置为 resolvconf

设置 D-Bus 只读权限

若需允许所有系统用户查看 iwd 的状态信息(但禁止修改配置),可创建一个 D-Bus 策略文件: /etc/dbus-1/system.d/iwd-allow-read.conf

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy context="default">
    <deny send_destination="net.connman.iwd"/>
    <allow send_destination="net.connman.iwd" send_interface="org.freedesktop.DBus.Properties" send_member="GetAll" />
    <allow send_destination="net.connman.iwd" send_interface="org.freedesktop.DBus.Properties" send_member="Get" />
    <allow send_destination="net.connman.iwd" send_interface="org.freedesktop.DBus.ObjectManager" send_member="GetManagedObjects" />
    <allow send_destination="net.connman.iwd" send_interface="net.connman.iwd.Device" send_member="RegisterSignalLevelAgent" />
    <allow send_destination="net.connman.iwd" send_interface="net.connman.iwd.Device" send_member="UnregisterSignalLevelAgent" />
  </policy>
</busconfig>

创建加密的网络配置文件

自 1.25 版本起,iwd 为基于 systemd 的系统提供了实验性的加密配置文件支持,可将网络凭据加密存储。 首先,利用 systemd-creds 创建一个绑定到系统可信平台模块 (TPM) 的加密凭据:

# systemd-ask-password -n | systemd-creds --tpm2-device=auto --name=iwd-secret encrypt - /etc/credstore.encrypted/iwd-secret.cred

随后,为 iwd 服务创建 drop-in 覆盖文件,使其加载该凭据: /etc/systemd/system/iwd.service.d/use-creds.conf

[Service]
LoadCredentialEncrypted=iwd-secret:/etc/credstore.encrypted/iwd-secret.cred

最后,在 iwd 主配置中启用凭据,并重载 systemd 服务: /etc/iwd/main.conf

[General]
SystemdEncrypt=iwd-secret

注意:配置完成后,现有的和未来新增的配置文件都将被自动加密。由于凭据隐式绑定到 TPM 的特定状态(如 PCR 7),若安全启动状态或固件证书发生更改,将导致无法解密并连接网络。


故障排除指北

1. 启用详细的 TLS 调试日志 在配置 MSCHAPv2 或 TTLS 等企业级安全认证时遇到问题,可以通过环境变量开启详细的 TLS 调试输出。创建 drop-in 配置文件: /etc/systemd/system/iwd.service.d/tls-debug.conf

[Service]
Environment=IWD_TLS_DEBUG=TRUE

重启服务后,可通过 journalctl -u iwd.service 查看详细日志。

2. 启动后需重新启动 iwd.service 的问题 部分设备在系统启动时可能因无线网卡尚未通电就启动了 iwd,导致服务无法正常工作。 解决方法是强制 iwd 等待相应的网络设备准备就绪。首先通过 systemctl list-units --type=device | grep wlan0 找到对应的设备单元,然后编辑服务文件: /etc/systemd/system/iwd.service.d/override.conf

[Unit]
After=sys-XXXX-net-wlan0.device
Wants=sys-XXXX-net-wlan0.device

(如果仍然无效,可尝试在 [Service] 块中添加 ExecStartPre=ip link set wlan0 up)

3. udev 未重命名无线网络设备 从 1.0 版本开始,iwd 会主动禁用网络接口的“可预测命名”规则。它通过安装 /usr/lib/systemd/network/80-iwd.link 文件阻止 udev 重命名接口,保留 wlan# 的传统内核命名方式,以避免重命名带来的竞态条件崩溃。 若这引发了其他系统兼容性问题,可以通过屏蔽该规则恢复重命名:

# ln -s /dev/null /etc/systemd/network/80-iwd.link

4. 接入点 (AP) 模式下无法分配 DHCP IP 当客户端连接到处于 AP 模式的 iwd 且无法获取 IP 时,必须在 /etc/iwd/main.conf 中开启内置网络配置:

[General]
EnableNetworkConfiguration=True

5. iwd 崩溃导致的 Wi-Fi 频繁断开 如果在日志中发现 iwd.service 崩溃重启,导致网络不断断开并重连,核心原因通常是系统中同时运行了多个冲突的网络管理服务。务必检查并确保只启用了一个网络管理器作为后端。

6. 客户端私钥加载失败错误 日志中若出现 Error loading client private key /path/to/key,表明内核的 pkcs8_key_parser 模块未加载。虽然 systemd 通常在启动时会自动加载,但刚完成初次安装且未重启时需要手动加载:

# modprobe pkcs8_key_parser

7. iwd 频繁漫游断线 如果信号太差,iwd 会自动断开当前连接并尝试漫游至其他已知 AP。日志通常显示:deauthenticating ... by local choice (Reason: 3=DEAUTH_LEAVING)。 可通过 iwctl station wlan0 show | grep RSSI 检查信号强度,并通过修改主配置文件降低漫游敏感度阈值: /etc/iwd/main.conf

[General]
RoamThreshold=-75
RoamThreshold5G=-80

8. DHCP 请求中未发送主机名 如果在路由器的客户端列表中无法看到主机名,需要在具体网络(而非主控文件)的配置中显式开启: /var/lib/iwd/SomeNetwork.psk

[IPv4]
SendHostname=true

9. /etc/resolv.conf 提示只读文件系统错误 当使用 resolvconf 作为 DNS 解析方法时,iwd 服务可能因权限问题无法写入 /etc/resolv.conf。为解决此问题,需为 iwd 增加写入权限。 创建覆盖文件: /etc/systemd/system/iwd.service.d/50-resolvconf.conf

[Service]
RuntimeDirectory=resolvconf
ReadWritePaths=/etc/resolv.conf

保存后重载并重启 iwd 服务使配置生效。

磁盘分区

磁盘分区(Disk partitioning)或磁盘切片是指在一个二级存储设备上创建一个或多个区域,以便对每个区域进行独立管理。

整个磁盘可以全部分配给一个单一分区,也可以为了多系统启动、维护交换(swap)分区,或为了在逻辑上分离音频、视频等数据文件而划分为多个分区。分区方案存储在**分区表(Partition table)**中,例如主引导记录(MBR)或全局唯一标识分区表(GPT)。

分区表通常使用各种分区工具进行创建和修改。分区通常直接包含文件系统,这通过在分区上创建文件系统(即格式化)来实现。或者,分区也可以包含 LVM(逻辑卷管理)、块设备加密或 RAID,这些技术最终会提供可在其上放置文件系统的设备文件(或者这些设备可以进一步堆叠)。任何直接包含可挂载文件系统的块设备(如磁盘、分区、LUKS 设备、LVM 逻辑卷或 RAID 阵列)都被称为卷(volume)


1 分区表

目前有两种主要的分区表类型可供选择:主引导记录(MBR)和全局唯一标识分区表(GPT)。此外,还有一种较少见的替代方案是使用无分区磁盘。

可以使用分区工具来查看块设备的分区表。

提示: 可以运行 parted /dev/sdX printfdisk -l /dev/sdX(其中 /dev/sdX 是块设备,例如 SATA 磁盘的 /dev/sda,NVMe 磁盘的 /dev/nvme0n1 或 eMMC 磁盘的 /dev/mmcblk0)来查看相关信息。

1.1 主引导记录 (MBR)

主引导记录(MBR)是存储设备的前 512 个字节。它包含操作系统的引导加载程序(boot loader)和存储设备的分区表,在 BIOS 系统的引导过程中起着重要作用。

注意: MBR 不位于任何分区内;它位于设备的第一个扇区(物理偏移量 0 处),在第一个分区之前。存在于无分区设备上或单个分区内的引导扇区被称为卷引导记录(VBR)

  • 引导代码区(Bootstrap code area): MBR 的前 440 个字节是引导代码区。在 BIOS 系统上,它通常包含引导加载程序的第一阶段。可以使用 dd 命令备份、恢复或擦除引导代码。
  • 分区表: 在 MBR 分区表(也称为 DOS 或 MS-DOS 分区表)中,存在 3 种类型的分区:
    1. 主分区(Primary)
    2. 扩展分区(Extended)
    3. 逻辑分区(Logical)

主分区可以是可引导的,并且每个磁盘或 RAID 卷最多只能有四个主分区。如果 MBR 分区表需要四个以上的分区,则需要将其中一个主分区替换为包含逻辑分区的扩展分区。扩展分区可以被视为逻辑分区的容器。一个硬盘最多只能包含一个扩展分区。扩展分区也算作一个主分区,因此如果磁盘有一个扩展分区,则只能再创建三个额外的主分区。扩展分区内可以存在的逻辑分区数量是不受限制的。如果系统需要与 Windows 双轨启动,Windows 必须位于主分区中。

通常的编号习惯是创建主分区 sda1sda3,然后是扩展分区 sda4sda4 上的逻辑分区编号为 sda5sda6 等。

提示: 在对 MBR 磁盘进行分区时,建议在磁盘末尾至少留下 33 个 512 字节扇区(16.5 KiB)的未分区可用空间,以防未来决定将其转换为 GPT 格式。这部分空间是备份 GPT 头所必需的。

1.2 全局唯一标识分区表 (GPT)

全局唯一标识分区表(GPT)是统一可扩展固件接口(UEFI)规范的一部分;它使用全局唯一标识符(GUIDs,在 Linux 世界中通常称为 UUIDs)来定义分区和分区类型。它旨在取代传统的 MBR 分区方案。

在 GPT 磁盘的起始处,有一个保护性主引导记录(PMBR),用于防止不支持 GPT 的软件误操作。这个保护性 MBR 与普通 MBR 一样,拥有一个引导代码区,可供支持 BIOS/GPT 引导的引导加载程序使用。

1.3 在 GPT 和 MBR 之间做出选择

GPT 是一种现代的替代分区方式;它旨在取代 MS-DOS 时代遗留下来的 MBR 系统。随着格式化工具的最新发展,无论是 GPT 还是 MBR 都能轻松获得良好的可靠性和性能。

注意: 要在基于 BIOS 的系统上使用 GRUB 或 Limine 从 GPT 分区的磁盘引导,需要一个 BIOS 引导分区(BIOS boot partition)

在选择时需要考虑以下几点:

  • 如果要在旧版 BIOS(Legacy BIOS)下与 Windows(32 位或 64 位)双轨启动,必须使用 MBR 方案。
  • 如果要使用 UEFI 模式与 64 位 Windows 双轨启动,必须使用 GPT 方案。
  • 如果在旧硬件(尤其是旧笔记本电脑)上安装,由于其 BIOS 可能不支持 GPT,建议考虑使用 MBR。
  • 如果对大于 2 TiB(约 2.2 TB)的磁盘进行分区,则必须使用 GPT。
  • 强烈建议在 UEFI 引导时始终使用 GPT,因为某些 UEFI 实现不支持在 UEFI 模式下从 MBR 引导。
  • 如果上述情况均不适用,则可以自由选择。由于 GPT 更为现代,通常推荐使用。

GPT 相较于 MBR 的优势包括:

  • 为每个分区提供唯一的磁盘 GUID 和唯一的分区 GUID(PARTUUID)——这是一种独立于文件系统的引用分区和磁盘的良好方式。
  • 提供独立于文件系统的分区名称(PARTLABEL)。
  • 支持任意数量的分区(取决于为分区表分配的空间)——无需扩展和逻辑分区。默认情况下,GPT 表包含定义 128 个分区的空间。
  • 使用 64 位 LBA 存储扇区号——最大可寻址磁盘大小为 2 ZiB。而 MBR 的寻址上限为每块硬盘 2 TiB。
  • 在磁盘末尾存储备用头部和分区表,有助于在主分区表损坏时进行恢复。
  • 使用 CRC32 校验和来检测头部和分区表的错误与损坏。

1.4 无分区磁盘与 Btrfs 分区

无分区磁盘(又称超级软盘,superfloppy)是指没有分区表的存储设备,只有一个文件系统占据整个设备。存在于无分区设备上的引导扇区被称为卷引导记录(VBR)。

Btrfs 分区:Btrfs 文件系统可以占据整个数据存储设备并取代 MBR 或 GPT 分区方案。通过 Btrfs 的子卷(subvolumes)功能,可以模拟出类似分区的结构。


2 分区方案

硬盘分区并没有严格的硬性规定,具体取决于所需的灵活性、速度、安全性以及可用磁盘空间的限制。这本质上是个人偏好问题。

注意:

  • UEFI 系统通常需要一个 EFI 系统分区(EFI system partition)
  • 对于使用 GPT 分区的 BIOS 系统,如果使用 GRUB 或 Limine 作为引导加载程序,则需要一个 BIOS 引导分区

2.1 单一根分区 (Single root partition)

考虑到消费级设备存储容量的增加,单一根分区方案是最简单、最灵活的,通常能满足大多数使用场景。可以创建一个交换文件(swap file)并根据需要轻松调整大小。通常建议从考虑单个 / 分区开始,然后根据特定用例(如 RAID、加密、共享媒体分区等)分离出其他分区。

对于单一根分区,建议的最小空间为 23–32 GiB。如果需要存储用户文件和使用交换文件,则需要更多空间。极其精简的安装大约需要 2 GiB。例如,一个简单的服务器可控制在 4 GiB 以内,而一个完整的 KDE Plasma 桌面安装可能需要 10 GiB。

警告: 除非引导加载程序能够访问驻留在 / 中的 /boot 目录,否则需要一个独立的物理 /boot 分区(存在于主分区表中,而不是在 LVM、软件 RAID 或文件系统子卷下)。这意味着引导加载程序必须支持从底层块设备、堆叠块设备(LVM、RAID 等)直到包含内核和 initramfs 镜像的文件系统的所有内容。

  • GPT 分区应具有“Linux root (x86-64)”类型 GUID:4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709(在 gdisk 中为 8304)。
  • MBR 分区应具有默认的“Linux”类型 ID:83

2.2 独立分区 (Discrete partitions)

将特定路径分离为独立分区允许为不同分区选择不同的文件系统和挂载选项。

/ (根目录)

根目录是文件系统层次结构的顶端。所有文件和目录都显示在根目录 / 下,即使它们存储在不同的物理设备上。根文件系统的内容必须足以进行引导、恢复、修复系统。因此,/ 下的某些目录不能作为独立分区分离出去(例如 /etc/usr 必须与 / 在同一分区,或在早期用户空间由 initramfs 挂载)。

/ 传统上包含 /usr 目录,该目录可能会随着软件的安装而显著增长。对于现代硬盘,15–20 GiB 对大多数用户来说应该足够了。如果计划在此处存储交换文件且不打算使用独立的 /var,可能需要更大的空间(即加上用于休眠的 RAM 内存大小以及额外的 8–12 GiB 用于 /var)。

/boot

包含内核(vmlinuz)和 initramfs 镜像、引导加载程序配置文件和各个引导阶段文件。正常运行系统不需要它,仅在引导和内核升级时需要。

警告: 引导加载程序必须能够访问 /boot 分区。建议使用 FAT32,因为它被几乎所有系统支持且不会出现不兼容的新特性。

  • 在 UEFI 系统上,可以将 EFI 系统分区直接挂载到 /boot 以避免创建额外的分区。
  • 在其他情况下,建议将分区类型设置为 Extended Boot Loader (XBOOTLDR) Partition,其 GPT GUID 为 BC13C2FF-59E6-4262-A352-B275FD6F7172(gdisk 中为 ea00),MBR ID 为 ea。建议大小为 1 GiB(如果仍有疑虑,4 GiB 绝对充足)。
/home

包含用户特定的配置文件、缓存、应用程序数据和媒体文件。分离出 /home 允许单独重新格式化 / 分区而不丢失用户数据。不建议在不同发行版之间共享同一用户的 home 目录,以免因软件版本不兼容引发问题。

  • GPT GUID: 933AC7E1-2EB4-4F13-B844-0E14E2AEF915(gdisk 为 8302)。
  • MBR ID: 83
交换空间 (Swap)

提供用作虚拟内存的磁盘空间。交换文件和交换分区性能相当,但文件更容易调整大小。目前的默认建议大小通常为 4 GiB。如果需要使用休眠(挂起到磁盘),建议创建与物理 RAM 大小相等的交换分区。

  • GPT GUID: 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F(gdisk 为 8200)。
  • MBR ID: 82
/data

可考虑挂载一个用于供所有用户共享文件的分区,这完全取决于实际需求。

  • GPT GUID: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
  • MBR ID: 83
/var

存储可变数据,如脱机目录、日志、pacman 的包缓存等。将其保持在独立分区中可避免因日志膨胀导致根分区耗尽空间。由于频繁读写,建议考虑将其放置在机械硬盘上。对于桌面系统,8–12 GiB 通常足够。

  • GPT GUID: 4D21B016-B534-45C2-A9FB-5C16E091FD2D(gdisk 为 8310)。
  • MBR ID: 83

2.3 示例布局

以下示例使用 /dev/sda 作为示例磁盘。对于 NVMe 磁盘(名称如 /dev/nvme0n1p1)或 eMMC 磁盘(名称如 /dev/mmcblk0p1),命名方案会有所不同。

UEFI/GPT 布局示例

安装系统挂载点 分区 分区类型 GUID 建议大小
/boot/efi /dev/sda1 C12A7328-F81F-11D2-BA4B-00A0C93EC93B: EFI 系统分区 1 GiB
[SWAP] /dev/sda2 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F: Linux swap 至少 4 GiB,若需休眠则为 RAM 大小
/ /dev/sda3 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709: Linux x86-64 root (/) 剩余空间。至少 23–32 GiB

BIOS/MBR 布局示例

安装系统挂载点 分区 分区类型 ID 引导标志 (Boot flag) 建议大小
[SWAP] /dev/sda1 82: Linux swap 至少 4 GiB,若需休眠则为 RAM 大小
/ /dev/sda2 83: Linux 剩余空间。至少 23–32 GiB
不适用 未分配空间 不适用 不适用 在磁盘末尾至少保留 16.5 KiB

BIOS/GPT 布局示例

安装系统挂载点 分区 分区类型 GUID 建议大小
/dev/sda1 21686148-6449-6E6F-744E-656564454649: BIOS 引导分区 1 MiB
[SWAP] /dev/sda2 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F: Linux swap 至少 4 GiB,若需休眠则为 RAM 大小
/ /dev/sda3 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709: Linux x86-64 root (/) 剩余空间。至少 23–32 GiB

3 分区工具

以下程序用于创建和/或操作设备分区表和分区。

3.1 常用命令行工具

名称 软件包 MBR GPT CLI TUI (终端界面) 脚本实用程序
fdisk util-linux fdisk(8) cfdisk(8) sfdisk(8)
GPT fdisk gptfdisk gdisk(8) cgdisk(8) sgdisk(8)
Parted parted parted(8) parted(8)

3.2 GUI 前端工具

  • blivet-gui:用于存储配置的图形工具。后端使用 parted。
  • GNOME Disks:GNOME 存储设备实用程序。后端使用 parted。
  • GParted:图形化磁盘分区编辑器。可调整大小、复制、移动分区且不丢失数据。
  • KDE Partition Manager:KDE 下管理磁盘和文件系统的实用工具。后端使用 sfdisk。

3.3 备份与恢复工具

  • 备份fdisk 可以创建分区表的备份;GPT fdisk 可以创建包括保护性 MBR、主 GPT 头、备份 GPT 头和分区表副本在内的二进制备份。
  • 恢复
    • gpart:可用于猜测和恢复被破坏的 MBR 分区表。
    • GPT fdisk:可以从备用 GPT 头恢复主 GPT 头,反之亦然。
    • TestDisk:支持恢复 MBR 和 GPT 上丢失的分区。

4 分区对齐与内核支持

  • 分区对齐:通常的经验法则是将分区的起始位置和大小对齐到兆字节(mebibytes)。需要注意的是,未对齐的分区将导致无法在 dm-crypt/LUKS 中使用 4096 字节的扇区。
  • GPT 内核支持:内核配置中的 CONFIG_EFI_PARTITION 选项启用了内核中的 GPT 支持。即使 GPT 磁盘仅用于数据存储而不用于引导,也需要启用此选项。该选项在官方支持的内核中默认开启。如果使用自定义内核,请确保编译时设置 CONFIG_EFI_PARTITION=y

5 故障排除

5.1 让旧版 BIOS 支持从 GPT 启动

一些较旧的 BIOS(2010 年以前)在解析引导扇区时,如果未找到可引导的 MBR 分区,将拒绝引导。在使用 GPT 分区方案时,BIOS 会认为里面只有一个非引导类型的保护性 MBR 分区(类型 ee)。

虽然可以使用 fdisk -t mbr /dev/sda 将其标记为可引导,但这违反了 UEFI 规范,可能导致现代 UEFI 系统上的启动问题。要创建一个既兼容现代 UEFI 又兼容挑剔的旧版 BIOS 的混合驱动器,可以通过输入以下字节序列手动添加一个虚拟的 MBR 分区条目(这不会干扰 GPT 结构):

printf '\200\0\0\0\0\0\0\0\0\0\0\0\001\0\0\0' | dd of=/dev/sda bs=1 seek=462

这将覆盖第二个 MBR 分区槽位,并添加一个类型为 0 的可引导分区,从而“欺骗”旧版 BIOS 允许启动。

5.2 固件 RAID 启用时驱动器不可见

如果 SATA 或 NVMe 驱动器在固件设置中可见,但对 Linux 不可见(如 fdisk -l 无法列出),可能是控制器处于固件 RAID 模式。

对于 NVMe,系统日志中可能会显示需要将 BIOS 从 RAID 切换到 AHCI 模式的提示。 解决方案是进入系统固件(BIOS/UEFI)设置,禁用 NVMe RAID 模式,并将 SATA 控制器操作模式从 RAID 更改为 AHCI。(注意,该设置可能被称为“Intel Rapid Storage Technology”、“Intel VMD controller”等)。

警告: 如果与 Windows 双轨启动,在更改控制器模式之前必须先在 Windows 端做好准备(如在 Windows 内启用 AHCI 模式),否则会导致 Windows 无法启动。

高级格式化(Advanced Format)与存储扇区配置

以下是基于提供的文档整理的详细技术笔记。内容涵盖了物理与逻辑扇区的概念、如何更改存储设备的扇区大小、分区对齐的最佳实践,以及在不同文件系统和加密工具中的具体应用。


1. 扇区基础概念

硬盘驱动器(HDD)的最小物理存储单元称为扇区(Sector),固态硬盘(SSD)的等效单元则是页(Page)。存储设备的固件会将物理扇区抽象为逻辑扇区,以便软件层进行操作。

  • 物理扇区大小(Physical Sector Size):
    • 指物理存储设备声明其能够原子性写入的最小单元。
    • 传统 HDD 的物理扇区大小为 512 字节。
    • 引入 高级格式化(Advanced Format) 后,HDD 的物理扇区增加至 4096 字节(4 KiB),从而提高了存储密度和纠错能力。
    • SSD 通常不会公开其真实的 NAND 闪存页大小(通常为 4 KiB 到 16 KiB),而是报告与逻辑扇区相同的物理扇区大小。NVMe SSD 如果支持,则使用“原子写入单元电源故障(AWUPF)”参数值。
  • 逻辑扇区大小(Logical Sector Size):
    • 也称为操作系统扇区大小,是暴露给操作系统和应用程序的地址单元。
    • 高级格式化 HDD 可能具有 4096 字节的物理扇区,但出于兼容性考虑,仍可能呈现 512 字节的逻辑扇区。
  • 层级一致性: 设备端、块设备层和文件系统应使用相同的扇区大小,以避免由于固件转换层的映射过程产生不必要的开销。

1.1 查询扇区大小

可以使用以下命令查询设备报告的逻辑和物理扇区大小:

lsblk -td

输出中的 LOG-SEC 代表逻辑扇区大小,PHY-SEC 代表物理扇区大小。

也可以直接查询 sysfs 节点:

cat /sys/class/block/drive/queue/physical_block_size
cat /sys/class/block/drive/queue/logical_block_size

对于 NVMe SSD 的特殊说明: NVMe SSD 报告的 PHY-SEC 通常仅反映逻辑扇区大小,并不代表真实的 NAND 页面大小。可以通过以下命令查看 NVMe 支持的 LBA(逻辑块地址)格式和原子写入单元信息:

nvme id-ns /dev/nvme0n1 | grep -i lbaf
nvme id-ctrl /dev/nvme0n1 | grep -i awupf

2. 更改扇区大小

警告: 更改驱动器的扇区大小将不可挽回地擦除驱动器上的所有数据。这属于需要低级格式化的复杂操作。

部分 NVMe SSD 和企业级 SATA HDD 支持通过标准命令(NVMe 的 Format NVM 或 ATA 的 SET SECTOR CONFIGURATION EXT)更改其报告的扇区大小,以匹配物理扇区,从而获得最佳性能。

2.1 高级格式化硬盘(HDD)

首先使用 hdparm 检查驱动器是否支持更改扇区大小:

hdparm -I /dev/sdX | grep 'Sector size:'
  • 512e 驱动器: 仅报告逻辑扇区 512 字节,物理扇区 4096 字节,且不可更改。需要确保后续文件系统和分区对齐至 4096 字节。
  • 4Kn 驱动器: 逻辑和物理扇区均为 4096 字节,开箱即可获得最佳性能。
  • 支持更改的驱动器: 会在输出中列出受支持的格式(如 Supported: 512 4096)。

如果要将支持的 SATA HDD 的逻辑扇区大小设置为 4096 字节,需执行:

hdparm --set-sector-size 4096 --please-destroy-my-drive /dev/sdX

注:对于 USB 连接的驱动器,USB 桥接器必须支持 SAT(SCSI/ATA 转换)。部分消费级 USB 桥接器可能会在更改扇区后导致驱动器无法使用。

2.2 NVMe 固态硬盘(SSD)

大多数 SSD 报告的逻辑块大小为 512 字节,但物理使用 4 KiB 或 8 KiB。使用 nvme-cli 工具结合 Identify Namespace 命令可以检查格式化的逻辑块地址大小(FLBAS):

nvme id-ns -H /dev/nvme0n1 | grep "Relative Performance"

输出会列出不同的 LBA 格式(如 Metadata SizeRelative Performance)。建议选择 Metadata Size 为 0 的格式,因为 Linux 对元数据的支持有限。

使用指定参数(如 --lbaf=1)更改 LBA 大小:

nvme format --lbaf=1 /dev/nvme0n1

警告: 某些 NVMe SSD 在启用 4K 扇区后,在重度随机读取负载下可能会出现间歇性不稳定。如果在投入重要数据前测试发现此问题,建议恢复至 512 字节扇区配置。

2.3 制造商专属工具

如果通用实用程序无效,可以使用硬件制造商提供的工具:

  • Intel / Solidigm: 使用 Intel MAS 工具(intel-mas-cli-tool)或 Solidigm 存储工具(solidigm-sst-storage-tool-cli)。注意这通常只更改报告的物理扇区大小。
  • Seagate: 提供 openSeaChest 工具包(因使用标准 ATA/NVMe 命令,也适用于非希捷硬盘)。
    • 检查支持的格式:openSeaChest_Format -d /dev/sdX --showSupportedFormats
    • 设置 4096 字节扇区:openSeaChest_Format -d /dev/sdX --setSectorSize=4096 --confirm this-will-erase-data-and-may-render-the-drive-inoperable

3. 分区对齐

正确对齐分区可避免过多的“读-改-写(read-modify-write)”周期。个人计算机的典型做法是将每个分区的起始位置和大小对齐到 1 MiB (1,048,576 字节) 的标记。这一标准能够被所有常用的页面和块大小(1 MiB, 512 KiB, 128 KiB, 4 KiB, 512 B)整除。

  • fdisk, cfdisk, sfdisk, gdisk, cgdisk: 均会自动处理分区对齐。
  • sgdisk: 默认仅对齐分区的起始位置。需使用 -I/--align-end 选项启用分区大小/结束位置对齐。
  • Parted: 仅对齐分区起始位置。创建分区时,必须以 mebibytes(MiB)或更大的 IEC 二进制单位指定分区的结束位置。

警告: 如果分区未对齐,将导致无法在 dm-crypt/LUKS 中使用 4096 字节扇区。


4. dm-crypt 加密配置

自 Cryptsetup 2.4.0 起,luksFormat 命令会自动检测 LUKS2 格式的最佳加密扇区大小。但前提是设备报告了正确的默认扇区大小。为确保最佳性能,Cryptsetup 强烈建议将驱动器的逻辑扇区大小配置为 4096 字节。

验证 LUKS2 卷使用的扇区大小:

cryptsetup luksDump device | grep sector

如果设备未正确报告扇区大小,可以在创建容器时强制指定 4 KiB 扇区:

cryptsetup luksFormat --sector-size=4096 device

注:如果指定的扇区大小与设备不对齐,该命令将会中止并报错。

若已使用错误的扇区大小进行了加密,可重新加密以修复(前提是内部文件系统的块大小必须为 4096 或其倍数):

cryptsetup reencrypt --sector-size=4096 device

5. 文件系统

不同的 mkfs 实用程序在处理 4Kn(物理 4096,逻辑 4096)、512e(物理 4096,逻辑 512)和 512n(物理 512,逻辑 512)驱动器时,其默认块大小行为存在差异。

mkfs 实用程序 512e 磁盘块大小 (字节) 512n 磁盘块大小 (字节)
mkfs.bcachefs 4096 512
mkfs.btrfs 4096 4096
mkfs.exfat 4096 512
mkfs.ext4 4096 1024 / 4096*
mkfs.fat 512 512
mkfs.f2fs 4096 4096
mkfs.ntfs 512 512
mkfs.xfs 4096 512
mkswap 4096 4096
zpool-create 512 512

* mkfs.ext4 对于小于 512 MiB 的文件系统默认为 1024 字节,大于等于 512 MiB 时默认为 4096 字节。

SMR 驱动器性能警告: 对于固件管理的叠瓦式磁记录(SMR)驱动器,如果其物理扇区为 4096 字节,但使用了 512 字节的逻辑文件系统扇区,将会对其性能造成严重负面影响。在进行高负载写入操作(如 RAID 重建、备份、大量小文件写入等)时,扇区转换层会超负荷运转,写入速度可能骤降至个位数兆字节/秒。

如果在设备未报告正确信息时,可以手动强制 mkfs 设置 4096 字节:

  • Bcachefs: bcachefs format --block_size=4096 /dev/device0
  • exFAT: mkfs.exfat -s 4096 /dev/device
  • ext4: mkfs.ext4 -b 4096 /dev/device
  • FAT: mkfs.fat -S 4096 /dev/device
  • NTFS-3G: mkfs.ntfs -Q -s 4096 /dev/device
  • UDF: mkfs.udf -b 4096 /dev/device
  • XFS: mkfs.xfs -s size=4096 /dev/device
  • ZFS: zpool create -o ashift=12 poolname raidz device0

6. 已知问题与故障排除

6.1 已知系统限制

  • Syslinux: 不支持扇区大小非 512 字节的 FAT 文件系统。
  • systemd-homed: 目前无法在 4Kn 驱动器及具有 4096 字节扇区大小的 LUKS 上正常运行。

6.2 NVMe 驱动器格式化失败

在尝试更改 NVMe LBA 格式时,如果遇到 INVALID_OPCODE(2001)INVALID_FORMAT 错误,可能是因为驱动器(在当前状态下)不支持 Format NVM 命令。

验证支持状态:

nvme id-ctrl /dev/nvme0 | grep oacs

观察 oacs(可选管理命令支持)字段的位掩码。Format NVM 支持对应于位 1(值 0x02)。如果该位未设置(如 0x1d 转二进制后右数第二位为 0),则无法更改 LBA 格式。

常见场景与解决思路: 部分驱动器(尤其是在支持 S0ix 现代待机的 Intel 平台上使用 Pyrite 安全标准的驱动器)在虽然支持该命令,但由于系统状态拒绝执行。

  • 修复/变通方案:
    1. 在固件/BIOS 中禁用 S0ix(现代待机),将睡眠模式设置为 S3 或 S2idle。
    2. 添加内核引导参数:mem_sleep_default=s2idle
    3. 在执行格式化命令前,将系统挂起并恢复(Suspend/resume)一次。
  • 已知受影响型号: Hynix PC601,Lenovo 与 Dell 的部分笔记本电脑,Samsung 和 WD SN750 驱动器。

Linux 设备文件与块设备

简介:什么是设备文件?

在类 Unix 操作系统中,设备文件(Device file,或称特殊文件)是连接硬件设备驱动程序的接口。在文件系统中,它们的表现形式与普通文件无异。

  • 存储位置:遵循文件系统层次结构标准(Filesystem Hierarchy Standard),Linux 系统中的设备文件均存放在 /dev 目录下。
  • 管理机制:在 Arch Linux 等现代发行版中,设备节点由 udev 系统负责动态管理。

1 块设备 (Block Devices)

块设备是一种特殊文件,主要用于提供对底层硬件设备的缓冲访问(Buffered access)。

1.1 块设备命名规则

块设备名称的开头部分指示了内核操作该设备所使用的驱动子系统。

⚠️ 核心警告:块设备的内核名称描述符并非持久化标识(Non-persistent)。在每次系统启动时,名称可能会发生变化,因此绝对不应在系统配置文件(如 fstab)中直接使用这些名称。

块设备的常见类别及命名规范如下:

  • SCSI 设备 (SCSI)

    • 适用设备:支持 SCSI 命令(SCSI、SAS、UASP)、ATA(PATA、SATA)或 USB 大容量存储的设备(如传统硬盘、SSD、U盘)。
    • 命名规则:以 sd 开头,后跟按发现顺序递增的小写字母(a, b, c...)。
    • 示例
      • /dev/sda:系统发现的第一个 SCSI 存储设备。
      • /dev/sde:系统发现的第五个 SCSI 存储设备。
  • NVMe 设备 (NVM Express)

    • 适用设备:通过 NVMe 接口连接的固态硬盘(SSD)。
    • 命名规则:以 nvme 开头,后接控制器编号(从 0 开始),然后是字母 n,最后是命名空间(Namespace)编号(从 1 开始)。
    • 注意:内核分配的命名空间编号不一定与硬件的 NVMe 命名空间 ID (NSID) 完全一致。
    • 示例
      • /dev/nvme0n1:控制器 0 上的第 1 个命名空间(首个控制器的首个设备)。
      • /dev/nvme2n5:控制器 2 上的第 5 个命名空间。
  • MMC 设备 (MultiMediaCard)

    • 适用设备:SD 卡、MMC 卡及 eMMC 存储设备(由内核的 mmc 驱动处理)。
    • 命名规则:以 mmcblk 开头,后跟从 0 开始递增的设备编号。
    • 注意:若 SD/MMC 读卡器通过 USB 接口连接,则会由 SCSI 子系统处理,并采用 sdX 的命名规则。
    • 示例
      • /dev/mmcblk0:系统发现的首个 MMC 设备。
  • SCSI 光盘驱动器 (SCSI Optical Disc Drive)

    • 适用设备:使用 SCSI 驱动子系统接口连接的光驱(ODD)。
    • 命名规则:以 sr 开头,后跟从 0 开始递增的编号。udev 通常会提供一个指向 /dev/sr0 的符号链接 /dev/cdrom(名称固定,与光盘类型无关)。
    • 示例/dev/sr0(首个光驱),/dev/cdrom(符号链接)。
  • 虚拟块设备 (virtio-blk)

    • 适用设备:虚拟机中连接到 virtio 块设备接口的驱动器。
    • 命名规则:以 vd 开头,后跟按顺序递增的小写字母。
    • 注意:需将其与 virtio-scsi 区分,后者模拟的是 SCSI 控制器,因此遵循 SCSI(sdX)命名约定。
    • 示例/dev/vda(首个虚拟驱动器)。
  • 分区 (Partitions)

    • 命名规则:分区的名称由“驱动器设备名”和“分区表中的分区号”组合而成。如果底层驱动器的名称以数字结尾(如 NVMe、MMC),则在驱动器名和分区号之间需加入字母 p 作为分隔符。
    • 示例
      • /dev/sda1/dev/sda 上的第 1 个分区。
      • /dev/nvme2n5p3/dev/nvme2n5 上的第 3 个分区。
      • /dev/mmcblk3p4/dev/mmcblk3 上的第 4 个分区。
      • /dev/loop0p2/dev/loop0(回环设备)上的第 2 个分区。

1.2 相关系统工具 (Utilities)

管理和查看块设备常用的核心工具有两个:

  • lsblk (列出块设备)

    • util-linux 软件包提供,用于以树状图展示系统中的块设备及其关联的分区。
    • 常用选项
      • --fs:显示文件系统类型、标签、UUID 及挂载点等详细信息。
      • -o--output:自定义输出列,可在识别多块磁盘时精准筛选信息(如 NAME, PTTYPE, PARTLABEL, FSTYPE, FSVER, LABEL, FSSIZE, FSAVAIL, FSUSE%, MOUNTPOINTS)。
    • 帮助信息:执行 lsblk --help 可获取所有支持的输出列列表。
  • wipefs (擦除设备签名)

    • 用于列出或擦除指定设备上的文件系统、RAID 或分区表签名(魔术字符串),使这些签名对 libblkid 库不可见。

    • 重要特性:该命令仅擦除签名,不会擦除文件系统本身或销毁设备上的实际数据。

    • 操作示例:擦除 /dev/sdb 上的所有签名,并在用户主目录下为每个被擦除的签名创建备份文件:

      ```bash
      wipefs --all --backup /dev/sdb
      ```
      

2 伪设备 (Pseudo-devices)

伪设备是指存在于 /dev 目录下,但没有对应物理硬件的特殊设备节点,常用于系统级的数据生成或丢弃操作。常见的伪设备包括:

  • /dev/random:用于生成加密安全的伪随机数。
  • /dev/shm:系统共享内存的挂载点。
  • /dev/null:空设备,写入其中的任何数据都会被丢弃,读取则立即返回文件结束符(EOF)。
  • /dev/zero:零设备,提供无限的空字符(Null bytes,\0)。
  • /dev/full:满设备,任何向其写入数据的尝试都会触发“设备空间不足(ENOSPC)”错误。
  • /dev/ttyX(X 为数字):代表系统的虚拟终端控制器(Virtual Console)。

LVM

在 Linux 环境下,逻辑卷管理器(LVM)提供了一种高度灵活的磁盘存储管理方式。以下笔记详细梳理了在 Arch Linux 中配置与安装 LVM 的完整流程与注意事项,旨在为公众提供一份全面且专业的参考指南。

为了更好地理解本文中的 LVM 存储层级概念(物理卷、卷组、逻辑卷之间的映射关系),可以参考以下架构图:


核心概述与前期准备

LVM 卷的创建与配置应当在系统的分区步骤与格式化步骤之间进行。切勿直接将基础物理分区格式化为根文件系统,文件系统的创建应在逻辑卷(LV)内部完成。

标准配置流程概述:

  1. 安装必备软件包(需包含 lvm2)。
  2. 创建用于存放物理卷(PV)的基础分区。
    • 若为单块磁盘:建议在单个大分区中建立一个 PV。
    • 若为多块磁盘:可在每块磁盘上分别创建分区并在其上建立对应的 PV。
  3. 创建卷组(VG),并将前述所有 PV 纳入该卷组中。
  4. 在卷组(VG)内部划分逻辑卷(LV)。
  5. 格式化逻辑卷并挂载。
  6. 在系统引导配置阶段,将 lvm2 钩子(hook)写入 /etc/mkinitcpio.conf 文件中。

⚠️ 关键警告 若使用的引导加载器原生不支持 LVM(目前已知仅 GRUB 能够良好支持 LVM),则 /boot 目录绝不能存放在 LVM 逻辑卷中。在此类情况下,必须创建一个独立的 /boot 分区并对其进行直接格式化。


1. 部署与安装操作

在常规的系统安装流程进行至“磁盘分区”阶段时,需暂停常规步骤,转而采用以下 LVM 专属分区与构建操作。

1.1 创建基础分区

首要任务是按需对物理磁盘进行基础分区设置。根据所选的分区表类型,需设置特定的分区属性以标识 LVM:

  • GUID 分区表 (GPT):需将分区类型 GUID 设定为 E6D6D379-F507-44C2-A23C-238F2A3DF928(在 fdisk 工具中标记为 Linux LVM,在 gdisk 工具中对应代码为 8e00)。
  • 主引导记录 (MBR):需将分区类型 ID 设定为 8e(即 fdisk 中 Linux LVM 的标准类型)。

1.2 创建物理卷 (PV)

通过以下命令可列出所有当前可用作物理卷的基础设备:

# lvmdiskscan

⚠️ 数据安全提示:执行后续操作前,务必核实设备标识符,选择错误的设备将导致严重的数据丢失。

在选定的设备上初始化物理卷(该命令会写入 LVM 专用标头):

# pvcreate DEVICE

注:这里的 DEVICE 可以是块设备、整块磁盘(如 /dev/sda)、具体分区(如 /dev/sda2)或回环设备。 示例pvcreate /dev/sda2

相关管理命令

  • 跟踪已创建的物理卷详情:pvdisplay
  • 获取物理卷状态摘要:pvscan
  • 排错提示:若设备存在残留的旧磁盘签名,可使用 wipefs 命令进行擦除。

1.3 创建与扩展卷组 (VG)

卷组是逻辑卷的容器,需建立在至少一个物理卷之上:

# vgcreate volume_group physical_volume

示例vgcreate VolGroup00 /dev/sda2

若需扩容卷组(例如添加新的磁盘或分区),执行以下扩展命令:

# vgextend volume_group physical_volume

示例:将 sdb1sdc 纳入现有卷组:

# vgextend VolGroup00 /dev/sdb1
# vgextend VolGroup00 /dev/sdc
  • 获取卷组增长与当前状态:vgdisplay
  • :虽然系统允许创建多个不同的卷组,但这会导致底层存储无法汇聚为“单一可用大磁盘”的形态。将磁盘加入带有故障盘的 RAID 或镜像组的操作逻辑与此类似。
1.3.1 物理卷与卷组的联合创建

LVM 支持通过一条命令同时完成多设备的物理卷初始化及卷组创建。 示例:使用三个不同设备一步创建名为 VolGroup00 的卷组:

# vgcreate VolGroup00 /dev/sda2 /dev/sdb1 /dev/sdc

此命令会自动检查设备,如有必要会先将其配置为物理卷,随后创建卷组。若检测到设备上存在旧文件系统,系统会抛出警告提示。

1.4 创建逻辑卷 (LV)

逻辑卷是最终用于格式化和挂载的“虚拟分区”。

💡 高级配置提示

  • 若需使用快照、逻辑卷缓存、精简配置 (Thin Provisioning) 或 RAID 功能,需参考更详细的 LVM 逻辑卷进阶文档。
  • 若计划将逻辑卷格式化为 ext4 文件系统,建议在卷组中保留至少 256 MiB 的空闲空间,以备 e2scrub(8) 工具使用。在使用 -l 100%FREE 创建最后一个逻辑卷时,可适当缩小分配比例以留出该空间。

创建基础逻辑卷: 指定容量、所属卷组与逻辑卷名称:

# lvcreate -L size volume_group -n logical_volume

示例lvcreate -L 10G VolGroup00 -n lvolhome(创建完成后,设备路径为 /dev/VolGroup00/lvolhome)。

基于特定物理卷创建逻辑卷: 可显式指定底层物理设备以优化性能(例如将根目录部署于高读写速度的 SSD,而将家目录放置于大容量机械硬盘):

# lvcreate -L 10G VolGroup00 -n lvolhome /dev/sdc1

分配所有剩余空间

# lvcreate -l 100%FREE volume_group -n logical_volume

相关管理与注意事项

  • 跟踪逻辑卷状态:lvdisplay
  • 为保障创建命令顺利执行,可能需要预先加载 device-mapper 模块:modprobe dm_mod
  • 建议初始分配较小的容量,预留部分卷组空间,以便日后根据实际需求灵活实施扩容。

1.5 格式化与挂载逻辑卷

新创建的逻辑卷对应的设备节点通常位于 /dev/VolumeGroupName/ 目录下。若节点未显示,可执行以下命令激活卷组并生成节点:

# modprobe dm_mod
# vgscan
# vgchange -ay

执行格式化与挂载

# mkfs.fstype /dev/volume_group/logical_volume
# mount /dev/volume_group/logical_volume /mountpoint

示例

# mkfs.ext4 /dev/VolGroup00/lvolhome
# mount /dev/VolGroup00/lvolhome /home

⚠️ 挂载警告 挂载时必须严格使用逻辑卷的设备路径(如 /dev/Volgroup00/lvolhome),绝对不可挂载底层的物理分区本身(如 /dev/sda2)。


2. 系统深度配置

配置 LVM 架构后,必须在内核引导配置阶段进行适配,以确保系统在启动时能够正确识别并加载逻辑卷。首要条件是确认 lvm2 软件包已妥善安装。 (注:在全新安装时,若处于 arch-chroot 环境执行 mkinitcpiolvm2 必须安装在 chroot 内部,否则会报出 Error: Hook 'lvm2' cannot be found 的错误。)

2.1 添加 mkinitcpio 钩子 (Hook)

若根文件系统(Root FS)部署在 LVM 之上,必须在初始化内存盘(initramfs)中启用相关的 mkinitcpio 钩子,否则系统将面临无法启动的风险。

修改配置文件 /etc/mkinitcpio.conf

  • 对于默认的基于 systemd 的 initramfs: 确保 systemdlvm2 钩子启用,将 lvm2 插入至 blockfilesystems 之间:

    HOOKS=(base systemd ... block lvm2 filesystems)
    
  • 对于基于 busybox 的 initramfs: 确保 udevlvm2 钩子启用:

    HOOKS=(base udev ... block lvm2 filesystems)
    

修改完成后,必须执行标准的 initramfs 镜像重新生成操作。

2.2 设定内核启动选项

在配置引导加载器(Bootloader)时,需确保 root= 内核参数准确指向对应的映射设备路径。 配置要求root= 参数必须引用逻辑卷的完整路径,例如:root=/dev/vg-name/lv-name

RAID / mdadm

独立磁盘冗余阵列(RAID,Redundant Array of Independent Disks)是一种存储技术,它将多个物理磁盘驱动器(或其分区)组合成一个逻辑单元。根据具体的 RAID 实现方式,该逻辑单元可以直接作为文件系统使用,也可以作为包含多个分区的透明层。

RAID 的核心目的在于根据所需的数据冗余度和性能要求,以不同方式在驱动器之间分配数据。正确的 RAID 级别可以防止硬盘故障导致的数据丢失、提升读写性能,或兼顾两者。本笔记详细解析了 RAID 的核心概念以及如何使用 mdadm 工具创建和管理软件 RAID。

⚠️ 核心警告: RAID 绝不能替代数据备份。在发生火灾、设备失窃或多块硬盘同时损坏时,RAID 无法保护数据安全。此外,配置 RAID 过程复杂,操作不当极易造成数据损毁,操作前务必进行全面备份。


1. RAID 级别详解

不同的 RAID 级别提供了不同的冗余与性能组合。若需要直观理解以下概念,可以结合图表辅助学习。

1.1 标准 RAID 级别

  • RAID 0 (条带化)

    通过条带化(Striping)技术将多个磁盘组合。它不提供任何数据冗余(实际上降低了整体可靠性),但能提供极大的速度优势。适用于对速度要求极高且不在乎数据丢失的场景(如交换分区)。 容量计算:最小组件分区的大小 × 组件分区总数。

  • RAID 1 (镜像)

    最直观的 RAID 级别:完全镜像(Mirroring)。只要有一块硬盘正常工作,阵列就能继续运行。在软件实现中,由于引导加载程序不理解 RAID 结构,RAID 1 是引导分区(/boot)的唯一选择,因为其组件分区可以作为普通分区被读取。 容量计算:阵列中最小组件分区的大小。

  • RAID 5 (分布式奇偶校验)

    至少需要 3 块物理硬盘。结合了 RAID 0 的速度/容量优势与 RAID 1 的冗余特性。数据被条带化分布,同时在所有成员盘上分布存储奇偶校验块(Parity blocks)。允许 1 块硬盘发生故障而不丢失数据。 注意:由于现代消费级大容量硬盘具有不可恢复读取错误(URE)率,在重建大容量(如 4TiB 以上)阵列时极易触发 URE 导致整体数据丢失,因此存储行业目前已不推荐使用 RAID 5

  • RAID 6 (双重奇偶校验) 至少需要 4 块物理硬盘。机制类似 RAID 5,但存储两个不同的奇偶校验块,允许 2 块硬盘同时发生故障。对 URE 的抵抗力更强。但由于性能开销较大,在多数场景下,采用 far2 布局的 RAID 10 通常是更优的选择。

1.2 嵌套 RAID 级别 (Nested RAID)

  • RAID 1+0 与 RAID 10

    结合了镜像与条带化。传统上称为 RAID 1+0,但在 Linux MD(多磁盘)中,RAID 10 被实现为一个单层结构,并支持多种布局:

    • near X 布局:在 Y 块磁盘上将每个数据块重复 X 次,数据块在镜像磁盘上的位置几乎相同(类似于标准的 RAID 1+0)。
    • far X 布局:旨在为镜像阵列提供条带化的读取性能。磁盘被划分为前半部分和后半部分,写入磁盘 1 前部的数据会镜像到磁盘 2 的后部。该布局极大地提升了顺序读取速度(媲美 RAID 0),代价是写入性能有轻微下降。在关注读取速度且要求冗余的场景中,建议首选 RAID 10 far 2
    • 限制警告mdadm 无法对采用 far X 布局的阵列进行在线扩容(reshape)。例如,无法使用 mdadm --grow 将 4x1TB 的容量直接升级到更大。若有持续扩容需求,应坚持使用 near X 布局。

1.3 RAID 级别对比表

RAID 级别 数据冗余 物理驱动器利用率 读取性能 写入性能 最少驱动器数
0 100% nX (极佳) nX (极佳) 2
1 50% 多进程读取最高 nX,否则 1X 1X 2
5 67% - 94% (n−1)X (优异) (n−1)X (优异) 3
6 50% - 88% (n−2)X (n−2)X 4
10, far2 50% nX (极佳,等同 RAID 0) (n/2)X 2
10, near2 50% 多进程读取最高 nX,否则 1X (n/2)X 2

(注:n 代表专用磁盘的数量,X 代表单块磁盘的基础性能)

1.4 LINEAR (线性模式)

将两个或更多设备映射为单一设备。不具备 RAID 0 的并行读写加速,但允许无缝拼接不同容量的磁盘。也可通过 dmsetup、LVM 或 Btrfs 实现。


2. RAID 的底层实现方式

  1. 软件 RAID (Software RAID):最灵活、最易用的方式。不依赖专有硬件或固件,完全由操作系统管理(如本指南所用的 mdadm,或通过 LVM、ZFS、Btrfs 实现)。
  2. 硬件 RAID (Hardware RAID):由安装在主板上的独立 RAID 阵列卡管理,拥有独立的处理器。对操作系统透明,通常需要专用驱动和管理软件。
  3. 伪 RAID (FakeRAID):主板 BIOS 或板载 RAID。虽然由固件配置,但实际运算依赖主机的 CPU,并未实现完整的硬件 RAID 功能。通常需要使用 dmraid 工具管理(例如 Intel Rapid Storage)。可以通过 lspci 命令检查是否为真正的硬件 RAID 控制器。

3. mdadm 配置与安装指南

mdadm 是 Linux 下管理纯软件 RAID 的标准工具,它可以将任意块设备(甚至 U 盘)组合成阵列。

3.1 准备与分区设备

在复用旧驱动器时,必须先清除旧的 RAID 配置信息(超级块):

mdadm --misc --zero-superblock /dev/drive

分区建议:

  • 建议对磁盘进行分区后再组建 RAID(不建议直接使用裸盘,以防未来更换故障盘时遇到麻烦)。
  • 预留空间:为了应对不同厂商或同型号硬盘之间微小的容量差异,强烈建议在磁盘末尾保留约 100 MiB 的未分配空间
  • GPT 分区表:将分区类型 GUID 设置为 A19D880F-05FC-4D3B-A006-743F0F84911E(在分区工具中通常显示为 Linux RAID 或代码 FD00)。
  • MBR 分区表:将分区类型 ID 设置为 0xDA(非文件系统数据,Arch Linux 推荐)。

3.2 构建阵列

使用 mdadm --create 命令创建阵列。创建后,后台会立即开始同步,可以使用 cat /proc/mdstat 查看进度。

  • 创建 2 盘位 RAID 1 示例:

    mdadm --create --verbose --level=1 --raid-devices=2 /dev/md/MyRAID1Array /dev/sdb1 /dev/sdc1
    
  • 创建 4 盘位 + 1 热备盘的 RAID 5 示例:

    mdadm --create --verbose --level=5 --raid-devices=4 /dev/md/MyRAID5Array /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1 --spare-devices=1 /dev/sdf1
    
  • 创建具有 far2 布局的 2 盘位 RAID 10 示例:

    mdadm --create --verbose --level=10 --raid-devices=2 --layout=f2 /dev/md/MyRAID10Array /dev/sdb1 /dev/sdc1
    

3.3 更新配置文件

创建阵列后,应将其明确写入配置文件,以确保系统重启后能正确识别(而不是盲目扫描所有设备):

mdadm --detail --scan >> /etc/mdadm.conf

更新配置后,可使用 mdadm --assemble --scan 命令手动组装阵列。

3.4 格式化 RAID 文件系统

为达到最佳性能,格式化时(以 ext4 为例)需要根据 RAID 参数计算并设置步长(stride)和条带宽度(stripe-width)。

  • Chunk size (块大小):阵列属性(默认通常为 512 KiB)。通过 mdadm --detail /dev/mdX | grep 'Chunk Size' 获取。
  • Block size (文件系统块大小):文件系统属性(ext4 默认为 4 KiB)。
  • 计算公式
    • stride = chunk size / block size
    • stripe width = 实际承载数据的物理磁盘数量 * stride

RAID 5 格式化示例(3 块数据盘,1 块校验盘,512K Chunk,4K Block): stride = 512 / 4 = 128 stripe width = 3 (数据盘) * 128 = 384

mkfs.ext4 -v -L myarray -b 4096 -E stride=128,stripe-width=384 /dev/md0

4. 在 RAID 上安装系统的特殊配置

如果根目录(Root FS)部署在 RAID 阵列上,在系统安装过程中必须完成以下额外配置(通常在 chroot 环境中进行):

  1. 记录配置:确保执行 mdadm --detail --scan >> /etc/mdadm.conf
  2. 配置 initramfs:编辑 /etc/mkinitcpio.conf,将 mdadm_udev 钩子(hook)添加到 HOOKS 数组中。然后重新生成 initramfs。每次修改 mdadm.conf 后都必须重新生成。
  3. 配置引导加载程序:内核参数 root= 必须指向阵列映射设备(例如 root=/dev/md/MyRAIDArray 或持久化标签 root=LABEL=Root_Label)。
  4. RAID 0 布局参数:对于 5.3.4 及以上版本的 Linux 内核,可能需要通过内核参数显式指定 RAID 0 布局,例如 raid0.default_layout=2

5. RAID 核心维护操作

5.1 数据清洗 (Scrubbing)

定期检查和修复静默数据错误(Bit Rot)。

  • 启动清洗echo check > /sys/block/mdX/md/sync_action
  • 查看进度cat /proc/mdstat
  • 安全停止echo idle > /sys/block/mdX/md/sync_action
  • 注意:RAID 1 和 RAID 10 在健康状态下也可能由于内核无缓冲写入而在过渡数据区域产生非 0 的错误匹配计数(mismatch count),这通常是误报,但仍建议定期执行清洗操作。

5.2 设备的移除与替换

在不关机的情况下处理故障磁盘:

  1. 标记为故障 (Fail)mdadm --fail /dev/md0 /dev/failing_array_member

  2. 移除设备 (Remove)mdadm --remove /dev/md0 /dev/failing_array_member

  3. 优雅替换(如果磁盘尚未完全损坏):先加入新盘,再要求系统替换。

    mdadm /dev/md0 --add /dev/sdc1
    mdadm /dev/md0 --replace /dev/sdb1 --with /dev/sdc1
    
  4. 彻底清除被移除盘的超级块mdadm --zero-superblock /dev/failing_array_member(警告:禁止在 LINEAR 或 RAID 0 上执行此操作!)。

5.3 阵列扩容与速度调优

  • 增加阵列磁盘数量:使用 --grow 选项。

    mdadm --grow /dev/md0 --raid-devices=4
    

    (注:对于 RAID 0,它没有热备盘概念,需要将 grow 和 add 合并到同一条命令中执行)

  • 扩充容量到最大:在更换了所有底层大容量硬盘后,执行 mdadm --grow /dev/md0 --size=max,随后必须相应地调整分区表和文件系统大小(例如使用 resize2fs)。

  • 修改后台同步速度限制(按需分配系统 IO 资源): 查看和修改 /proc/sys/dev/raid/speed_limit_minspeed_limit_max

    sysctl -w dev.raid.speed_limit_min=600000
    sysctl -w dev.raid.speed_limit_max=600000