40 - 文件系统深入

文件系统是操作系统与存储设备之间的桥梁。从 ext4 的日志机制到 Btrfs 的写时复制,从 XFS 的分配组到 ZFS 的检查池,Linux 生态拥有丰富多样的文件系统选择。本章深入 VFS 层架构,对比主流文件系统的内部设计,讲解挂载策略、文件系统检查与创建,以及性能基准测试。


40.1 磁盘基础:扇区、分区与分区表

磁盘物理结构

磁盘(/dev/sda, /dev/nvme0n1)
 └── 扇区(Sector):最小物理读写单位(通常 512 字节或 4096 字节)
 └── 分区(Partition):磁盘上的逻辑区域
 └── 文件系统:组织分区内数据的结构
# 查看磁盘扇区信息
fdisk -l /dev/sda
# Sector size (logical/physical): 512 bytes / 4096 bytes
# 逻辑扇区 512B(软件兼容),物理扇区 4KB(硬件实际)
 
# 查看 NVMe 扇区
sudo nvme id-ns /dev/nvme0n1 | grep -i size
 
# 查看块设备队列参数
cat /sys/block/sda/queue/physical_block_size
cat /sys/block/sda/queue/logical_block_size

MBR vs GPT

特性MBR(传统)GPT(现代)
最大磁盘容量2TB9.4ZB(理论无限)
最大分区数4 个主分区(或 3 + 扩展)128 个(可扩展)
冗余备份无(分区表保存在磁盘首部)有(头部 + 尾部各一份)
CRC 校验
引导方式BIOS LegacyUEFI(也支持 BIOS 兼容)
分区标识1 字节类型码GUID(全局唯一标识符)
# 查看分区表类型
sudo fdisk -l /dev/sda | grep "Disklabel type"
# Disklabel type: gpt / dos
 
sudo parted /dev/sda print | head

40.2 VFS:虚拟文件系统层

VFS(Virtual File System)是 Linux 内核中的一个抽象层,为所有文件系统提供统一的操作接口。

graph TB
 APP[应用程序]
 VFS[VFS 虚拟文件系统]
 EXT[ext4]
 XFS[ XFS ]
 BTRF[Btrfs]
 ZFS[ ZFS ]
 F2[F2FS]
 NFS[ NFS ]
 TMP[tmpfs]
 BLOCK[通用块层]

 APP --> VFS
 VFS --> EXT
 VFS --> XFS
 VFS --> BTRF
 VFS --> ZFS
 VFS --> F2
 VFS --> NFS
 VFS --> TMP
 EXT --> BLOCK
 XFS --> BLOCK
 BTRF --> BLOCK
 F2 --> BLOCK
 TMP --> BLOCK

 style VFS fill:#fff9c4,stroke:#333

VFS 的四个核心对象:

对象内核数据结构含义示例
superblockstruct super_block描述已挂载的文件系统每个挂载点一个
inodestruct inode描述一个文件(不含文件名)权限、大小、数据块位置
dentrystruct dentry目录项,关联文件名与 inode路径查找
filestruct file描述一个打开的文件读写位置、文件标志
路径查找过程(以 /home/user/file.txt 为例):
 根 dentry → "home" dentry → "user" dentry → "file.txt" dentry → inode → 数据块
# 查看当前支持的文件系统
cat /proc/filesystems
 
# 查看 VFS 缓存统计
cat /proc/sys/vm/vfs_cache_pressure # 默认 100,降低此值可保留更多 dentry 缓存
cat /proc/slabinfo | grep dentry # dentry 缓存使用情况

40.3 ext4 文件系统

ext4 是 Linux 上使用最广泛的文件系统,是 ext3/ext2 的演进版本。

核心特性

特性说明
extents(区段)替代 ext3 的间接块映射,降低大文件寻址开销
journal(日志)元数据变更先写日志,保证文件系统一致性
延迟分配(delayed allocation)写入时先分配缓存,提交到磁盘时才分配物理块
多块分配一次分配多个连续块,减少碎片
在线碎片整理e4defrag
文件系统校验e2fsck,并支持元数据校验和

日志模式

模式挂载选项行为风险
data=ordered默认元数据日志化,数据先于元数据写入最低风险
data=writebackdata=writeback仅元数据日志化,不保证数据顺序可能产生文件垃圾
data=journaldata=journal所有数据写入日志(两次写入)最安全但最慢
# 创建 ext4 文件系统
sudo mkfs.ext4 -L "data" /dev/sda1
 
# 创建时指定参数
sudo mkfs.ext4 -b 4096 -i 16384 -I 256 -O ^has_journal /dev/sda1
# -b 块大小 -i inode 比(每多少字节一个 inode)
# -I inode 大小 -O ^has_journal 关闭日志
 
# 查看 ext4 文件系统信息
sudo tune2fs -l /dev/sda1
sudo dumpe2fs -h /dev/sda1
 
# 文件系统检查
sudo e2fsck -f /dev/sda1 # 强制检查
sudo e2fsck -p /dev/sda1 # 自动修复(preen)
 
# 碎片整理
sudo e4defrag /mnt/data # 整理整个分区
sudo e4defrag /path/to/file # 整理单个文件
 
# 调整 ext4 文件系统大小
sudo resize2fs /dev/sda1 # 扩展到分区大小
sudo resize2fs /dev/sda1 100G # 指定目标大小(需分区先扩展/缩小)

superblock 与 inode

# 查看 superblock 信息
sudo dumpe2fs /dev/sda1 | grep -i "superblock\|block count\|inode count"
 
# 备份 superblock 的位置
sudo dumpe2fs /dev/sda1 | grep "Backup superblock"
# 主 superblock 损坏时可用备用手动恢复:
# sudo e2fsck -b 32768 /dev/sda1

40.4 XFS 文件系统

XFS 是由 SGI 开发的高性能 64 位日志文件系统,是 RHEL/Fedora 的默认选择。

核心特性

特性说明
分配组(Allocation Groups)将文件系统划分为多个独立管理区域,支持并行 I/O
B+ 树索引所有元数据使用 B+ 树组织,查找效率高
延迟分配写入时最大化分配连续空间
在线扩展支持在线增大文件系统(不支持缩小)
预分配对追加写入场景(日志文件)的预留空间
# 创建 XFS 文件系统
sudo mkfs.xfs -L "data" /dev/sda1
sudo mkfs.xfs -b size=4096 -d agcount=4 /dev/sda1 # 指定块大小和分配组数
 
# 查看 XFS 信息
sudo xfs_info /mnt/data
sudo xfs_admin -l /dev/sda1 # 查看 label
sudo xfs_admin -u /dev/sda1 # 查看 UUID
 
# 在线扩展(XFS 不支持缩小)
sudo xfs_growfs /mnt/data
sudo xfs_growfs -D 100000 /mnt/data # 指定数据块数
 
# 文件系统检查与修复
sudo xfs_repair /dev/sda1 # 检查并修复(需未挂载)
sudo xfs_repair -n /dev/sda1 # 仅检查不修复
sudo xfs_db -c "check" /dev/sda1 # 基础健康检查
 
# 碎片整理
sudo xfs_fsr /mnt/data # 整理整个文件系统
sudo xfs_fsr -v /path/to/file # 整理特定文件
 
# 冻结/解冻(备份时使用)
sudo xfs_freeze -f /mnt/data # 冻结写入
sudo xfs_freeze -u /mnt/data # 解冻

XFS 与 ext4 选择建议

场景推荐理由
通用桌面ext4兼容性最好,工具链成熟
大文件服务器XFS分配组设计,并行 I/O 好
数据库XFS延迟分配、预分配,适合大块随机 I/O
需要缩容ext4XFS 不支持缩小
RHEL/Fedora 默认XFSRHEL 7+ 默认文件系统

40.5 Btrfs 文件系统

Btrfs(B-tree File System)是 Linux 的现代写时复制(CoW)文件系统,内置了卷管理、快照、压缩等高级功能。

核心特性

特性说明
写时复制(CoW)修改数据时先写新位置,再更新引用,保证数据一致性
子卷(Subvolume)文件系统内部的独立命名空间,可分别挂载
快照(Snapshot)子卷的时间点只读/可写副本,空间效率高
压缩透明压缩(zlib, lzo, zstd),以文件或卷为单位
RAID 支持内置 RAID0/1/10/5/6(RAID5/6 有已知问题)
数据校验数据和元数据均有校验和
在线扩展/缩小支持在线调整大小
去重离线或在线去重(duperemove, bees)
# 创建 Btrfs 文件系统
sudo mkfs.btrfs -L "data" /dev/sda1
sudo mkfs.btrfs -m raid1 -d raid1 /dev/sdb /dev/sdc # RAID1
sudo mkfs.btrfs -m raid0 -d raid0 /dev/sdb /dev/sdc # RAID0
 
# 查看文件系统信息
sudo btrfs filesystem show /
sudo btrfs filesystem df / # 空间使用(比 df 更准确)
sudo btrfs filesystem usage /
 
# 子卷操作
sudo btrfs subvolume create /mnt/btrfs/@home
sudo btrfs subvolume list /mnt/btrfs
sudo btrfs subvolume delete /mnt/btrfs/@snap
 
# 快照
sudo btrfs subvolume snapshot /mnt/btrfs/@home /mnt/btrfs/@home_snap
sudo btrfs subvolume snapshot -r /mnt/btrfs/@home /mnt/btrfs/@home_ro_snap
# 快照几乎瞬间完成,占用空间极小(共享未修改数据)
 
# 压缩
sudo btrfs filesystem defrag -czstd -r /path # zstd 压缩
sudo mount -o compress=zstd /dev/sda1 /mnt # 挂载时指定压缩算法
sudo chattr +c /mnt/data # 标记为自动压缩
 
# 清除与平衡
sudo btrfs scrub start / # 数据校验检查
sudo btrfs scrub status /
sudo btrfs balance start / # 平衡数据分布
 
# 磁盘替换与扩容
sudo btrfs device add /dev/sdd /mnt # 添加磁盘
sudo btrfs device remove /dev/sda /mnt # 移除磁盘(迁移数据)
 
# 修复
sudo btrfs check /dev/sda1 # 文件系统检查(未挂载)
sudo btrfs check --repair /dev/sda1 # 修复(谨慎!)
sudo btrfs rescue super-recover /dev/sda1 # superblock 恢复

Btrfs 成熟度说明

Btrfs 在单磁盘和 RAID1(元数据和数据双份)上已相当稳定,openSUSE 和 Fedora 已将 Btrfs 作为默认文件系统。RAID5/6 存在已知问题,不建议用于生产环境。

更多 Btrfs 详细用法参考 10-Btrfs高级玩法


40.6 ZFS 文件系统

ZFS 是一个将文件系统、卷管理器、RAID 控制器融为一体的综合存储方案,以数据完整性、快照和数据压缩为核心优势。

核心概念

zpool(存储池) ← 由 vdev(虚拟设备)组成
 └── vdev ← 由物理磁盘组成(mirror, raidz, raidz2...)
 └── zfs dataset ← 数据集(文件系统或 zvol)
 └── files / blocks
特性说明
数据完整性所有数据和元数据均有端到端校验和
快照与克隆几乎零成本的快照,可写克隆
发送与接收zfs send / recv 用于增量备份和同步
压缩透明压缩(lz4, zstd, gzip 等多种算法)
去重在线去重(dedup)
自适应替换缓存(ARC)智能内存缓存
ZIL / SLOG意图日志 / 独立日志设备,加速同步写
# 安装 ZFS
# Ubuntu:
sudo apt install zfsutils-linux
# Debian: 需要添加 contrib 源
# Fedora: 从 RPM Fusion 或自行编译
# RHEL: 使用 OpenZFS 仓库或 kmod 包
 
# 创建存储池
sudo zpool create tank mirror /dev/sdb /dev/sdc # 镜像池
sudo zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd # RAIDZ1(类似 RAID5)
sudo zpool create tank raidz2 /dev/sdb /dev/sdc /dev/sdd /dev/sde # RAIDZ2
 
# 创建数据集
sudo zfs create tank/data
sudo zfs create tank/data/documents
sudo zfs set compression=lz4 tank/data
sudo zfs set atime=off tank/data
 
# 快照
sudo zfs snapshot tank/data@backup-2024-01-01
sudo zfs rollback tank/data@backup-2024-01-01
 
# 发送/接收(增量备份)
sudo zfs send tank/data@snap1 | ssh remote sudo zfs recv backup/data
 
# 增量发送
sudo zfs send -i tank/data@snap1 tank/data@snap2 | ...
 
# 空间管理
sudo zfs list
sudo zpool list
sudo zpool status
sudo zfs get all tank/data

ZFS 因为许可问题(CDDL),多数 Linux 发行版不将其包含在主线内核中,需要额外安装模块。Ubuntu 是重要的例外,提供了较好的 ZFS 支持。


40.7 F2FS 与闪存优化

F2FS(Flash-Friendly File System)是三星专门为 NAND 闪存存储(SSD、eMMC、UFS)设计的文件系统。

为什么需要 F2FS

传统文件系统(ext4、XFS)是为旋转磁盘(HDD)设计的,不充分理解 SSD 的内部结构:

  • FTL(Flash Translation Layer):SSD 内部将逻辑地址映射到物理块
  • 垃圾回收(GC):SSD 内部需要定期清理无效页
  • 写放大(Write Amplification):文件系统写入 4KB,SSD 内部可能写入 16KB+

F2FS 通过日志结构(Log-structured)设计减少写放大,与 SSD 的 FTL 更协调。

# 创建 F2FS 文件系统
sudo mkfs.f2fs /dev/sdc1
sudo mkfs.f2fs -l "ssd-data" -O extra_attr,inode_checksum /dev/sdc1
 
# 挂载建议选项
sudo mount -o noatime,nodiratime,background_gc=on,discard /dev/sdc1 /mnt/ssd
 
# 查看 F2FS 信息
sudo fsck.f2fs /dev/sdc1

40.8 tmpfs 与 ramfs

这两种文件系统将数据存储在内存中(而非磁盘),特点是极快的读写速度和系统重启后数据丢失。

特性tmpfsramfs
大小限制可限制(默认 RAM 的 50%)无限制(可能导致 OOM)
和 swap 的关系内存不足时可换出到 swap始终驻留在 RAM 中
推荐使用否(除非有特殊需求)
# tmpfs 示例(/tmp 通常是 tmpfs)
mount | grep tmpfs
 
# 手动挂载 tmpfs
sudo mount -t tmpfs -o size=2G,mode=1777 tmpfs /mnt/ramdisk
 
# 常见的 tmpfs 挂载点
# /dev/shm: 共享内存(POSIX shm)
# /run: 系统运行时数据
# /tmp: 临时文件(部分发行版)
 
# 查看 tmpfs 使用量
df -h /dev/shm /run /tmp

40.9 挂载选项与 /etc/fstab

常用挂载选项

选项效果推荐场景
defaultsrw, suid, dev, exec, auto, nouser, async通用
noatime不更新访问时间所有场景(性能优化)
relatime只在 mtime/ctime 更新时更新 atime通用(Linux 默认)
nodiratime不更新目录访问时间配合 noatime
data=orderedext4 数据顺序写入ext4 默认,推荐
compress=zstdBtrfs 透明压缩Btrfs
autodefragBtrfs 自动碎片整理Btrfs
discard / discard=asyncSSD TRIM 支持SSD
nofail挂载失败不阻止启动非关键分区
exec / noexec允许/禁止执行二进制文件安全加固
nosuid忽略 SUID/SGID 位安全加固
nodev不解释字符/块设备安全加固
ro只读挂载恢复模式 / 归档

fstab 格式

# /etc/fstab 格式
# <设备/UUID> <挂载点> <文件系统类型> <选项> <dump> <fsck顺序>
 
# 示例
UUID=12345678-abcd-... / ext4 defaults,noatime 0 1
UUID=abcd1234-ef12-... /boot ext4 defaults 0 2
UUID=FEDC-abcd1234 /boot/efi vfat umask=0077 0 1
# swap
UUID=7890abcd-... none swap sw 0 0
# tmpfs
tmpfs /tmp tmpfs size=4G,noatime 0 0
# 网络文件系统
server:/export /mnt/nfs nfs defaults,_netdev 0 0
# 查看分区 UUID
sudo blkid
ls -l /dev/disk/by-uuid/
 
# 测试挂载(不实际写入 fstab)
sudo mount -a --fake
 
# 验证 fstab 配置
sudo findmnt --verify

40.10 文件系统检查与修复

fsck 原理

fsck 在系统启动时根据 fstab 中 pass 列(第 6 列)的值决定检查顺序:

pass 值含义
0不检查
1根文件系统,最先检查
2其他文件系统,可以并行检查
# 强制下次启动时检查根文件系统
sudo touch /forcefsck # 大多数发行版
sudo tune2fs -c 1 /dev/sda1 # ext4:每挂载 1 次后检查
 
# 查看 ext4 文件系统下次检查的条件
sudo tune2fs -l /dev/sda1 | grep -E "Mount count|Maximum mount count|Last checked|Check interval"
 
# 手动检查(必须先卸载或只读挂载)
sudo e2fsck -f /dev/sda1 # ext4
sudo xfs_repair /dev/sda1 # XFS
sudo btrfs check /dev/sda1 # Btrfs(未挂载)
sudo fsck.f2fs /dev/sdc1 # F2FS

40.11 文件系统性能基准测试

fio(Flexible I/O Tester)

# 安装
sudo apt install fio
sudo dnf install fio
 
# 随机读取测试(4K 随机读,模拟日常)
fio --name=randread --ioengine=libaio --rw=randread \
 --bs=4k --numjobs=4 --size=1G --runtime=30 --time_based \
 --filename=/mnt/testfile
 
# 随机写入测试
fio --name=randwrite --ioengine=libaio --rw=randwrite \
 --bs=4k --numjobs=4 --size=1G --runtime=30 --time_based \
 --filename=/mnt/testfile
 
# 顺序读取
fio --name=seqread --ioengine=libaio --rw=read \
 --bs=1M --numjobs=1 --size=4G --runtime=30 --time_based \
 --filename=/mnt/testfile
 
# 顺序写入
fio --name=seqwrite --ioengine=libaio --rw=write \
 --bs=1M --numjobs=1 --size=4G --runtime=30 --time_based \
 --filename=/mnt/testfile
 
# 混合读写(70% 读 30% 写)
fio --name=mixed --ioengine=libaio --rw=randrw --rwmixread=70 \
 --bs=4k --numjobs=4 --size=1G --runtime=30 --time_based \
 --filename=/mnt/testfile

bonnie++

# 安装
sudo apt install bonnie++
sudo dnf install bonnie++
 
# 运行测试
bonnie++ -d /mnt/data -s 4G -n 0 -m bonnie-test -x 3 -r 2G
# -s: 测试文件大小(需大于 RAM 避免缓存)
# -n: 小文件数(0=不测试)
# -x: 重复次数
# -r: RAM 大小(正确指导缓存排除)

简单对比测试

# 使用 dd 粗略测试顺序写入速度
dd if=/dev/zero of=/mnt/data/testfile bs=1M count=4096 conv=fdatasync
 
# 使用 dd 粗略测试顺序读取速度(清除缓存后)
echo 3 | sudo tee /proc/sys/vm/drop_caches
dd if=/mnt/data/testfile of=/dev/null bs=1M count=4096
 
# 注意:dd 测试可能受缓存影响,fio 更精确

40.12 文件系统选择指南

场景推荐文件系统理由
通用桌面 Linuxext4稳定、兼容性最好
通用服务器XFS大规模扩展性好、大文件 I/O 强
数据库XFS / ext4成熟稳定,工具链丰富
NAS / 数据归档ZFS / Btrfs快照、校验和、数据自愈合
SSD 专用F2FS / BtrfsF2FS 闪存优化、Btrfs 压缩
容器 / 不可变系统Btrfs / overlay2快照、写时复制、高效分层
嵌入式系统ext4 / F2FS轻量、广泛支持
安装程序默认跟随发行版RHEL/Fedora → XFS,Ubuntu → ext4,openSUSE → Btrfs

40.13 小结

文件系统设计哲学核心优势核心局限
ext4传统日志型极端稳定,工具链完善缺乏现代特性(CoW、快照)
XFS高性能并行大文件 I/O 出色不支持缩小
BtrfsCoW + 卷管理一体快照、压缩、子卷RAID5/6 不成熟
ZFS存储池 + 完整性数据校验、快照、去重许可限制,内存占用大
F2FS闪存原生优化低写放大,SSD 友好年轻,桌面支持有限
tmpfs纯内存文件系统极致速度重启数据丢失

交叉链接:文件系统知识与存储管理紧密相连,延伸阅读 12-存储管理与磁盘操作36-文件系统设计。具体发行版的 Btrfs 深度玩法见 10-Btrfs高级玩法。文件系统的备份恢复参考 17-备份与恢复