文件系统

来自 Arch Linux 中文维基

根据维基百科

文件系统控制数据的读和写。如果没有文件系统,储存介质里的信息就会变成一块无法理解的数据。通过把数据分块、命名,不同的信息就可以被隔离、分辨。每组数据被命名为“文件”是取自纸质信息系统的命名方式。而“文件系统”是指用于管理信息的分组和命名的结构和逻辑规则。

文件系统有很多,每个磁盘分区可以而且只可以使用其中的某一个。每种文件系统有自己的优缺点和独有特性。以下内容是目前所支持的文件系统类型的概述,相应的链接会提供更加详细的信息。

文件系统类型[编辑 | 编辑源代码]

filesystems(5) 包含一个简单介绍,详细比较参考 Wikipedia:Comparison of file systems。内核已经加载和内置的文件系统可以通过 /proc/filesystems 查看。通过 ls /lib/modules/$(uname -r)/kernel/fs 可以查看所有的内核模块。

in-tree 和 FUSE 文件系统
文件系统 创建命令 工具 Archiso [1] 内核文档 [2] 说明
Btrfs mkfs.btrfs(8) btrfs-progs [https://docs.kernel.org/filesystems/btrfs.html btrfs.html 可靠性
VFAT mkfs.fat(8) dosfstools vfat.html Windows 9x 的文件系统
exFAT mkfs.exfat(8) exfatprogs 从 Linux 内核 5.4 开始,内核原生支持该文件系统 [3]
mkexfatfs(8) exfat-utils N/A (FUSE-based)
F2FS mkfs.f2fs(8) f2fs-tools f2fs.html 基于闪存的设备
ext3 mkfs.ext3(8) e2fsprogs ext3.html
ext4 mkfs.ext4(8) e2fsprogs ext4.html
HFS mkfs.hfsplus(8) hfsprogsAUR hfs.html Classic Mac OS 文件系统
HFS+ mkfs.hfsplus(8) hfsprogsAUR hfsplus.html macOS (8-10.12) 文件系统
JFS mkfs.jfs(8) jfsutils jfs.html
NILFS2 mkfs.nilfs2(8) nilfs-utils nilfs2.html 原始闪存设备,如 SD 卡
NTFS ntfs3.html Windows NT 文件系统。从 Linux 5.15 起可用的新驱动
ntfs-3g[4] ntfs.html 旧驱动。写入支持很有限。官方支持的内核构建时不包含CONFIG_NTFS_FS,因此不可用。
mkfs.ntfs(8) N/A (FUSE-based) 有较多功能的 FUSE 驱动。
ReiserFS mkfs.reiserfs(8) reiserfsprogs ReiserFS 已经从 Linux 5.18 中弃用并且计划于2025年从内核中移除。
UDF mkfs.udf(8) udftools udf.html
XFS mkfs.xfs(8) xfsprogs

xfs.html
xfs-delayed-logging-design.html
xfs-self-describing-metadata.html

ZFS zfs-linuxAUR N/A (OpenZFS 移植)
注意: 内核中有 NTFS 驱动(参考ntfs.html),但是文件写入支持很有限。
代码在单独仓库的文件系统
文件系统 创建命令 内核补丁 用户空间工具 说明
APFS mkapfs(8) linux-apfs-rw-dkms-gitAUR apfsprogs-gitAUR macOS (10.13 和更新) 文件系统,只读,实验版本.
Bcachefs bcachefs(8) linux-bcachefs-gitAUR bcachefs-tools-gitAUR
Reiser4 mkfs.reiser4(8) reiser4progsAUR
ZFS zfs-linuxAUR, zfs-dkmsAUR zfs-utilsAUR OpenZFS port

文件系统日志[编辑 | 编辑源代码]

以上除了 ext2 、FAT16/32(即VFAT)、Reiser4(可选开启)、Btrfs 和 ZFS 以外的文件系统都使用文件系统日志。文件系统日志通过在数据更改写入储存设备前把变更写入日志来提供故障恢复能力。当出现系统崩溃或电源故障的时候,这些文件系统能够更快的恢复到可用状态,并且在恢复过程中更不容易出现错误。日志活动在文件系统中专用的一部分空间里进行。

并非所有的日志技术都相同。ext3 和 ext4 提供 data-mode journaling,同时记录数据本身和元数据(也有可以只记录元数据变化)。这个模式对性能影响很大,默认是禁用的。

与此类似,Reiser4 的名为 "transaction models" 的模式不仅改变了它所提供的功能,也改变了它的日志模式。这种日志记录模式使用了特别的日志技术,wandering logs,来确定使用哪种写入策略:写入储存器两次; write-anywhere,纯粹的 copy-on-write(和 btrfs 的类似,不过用的是另一种树设计);hybrid,在前两种之间智能切换。

注意: Reiser4 通过 node41 插件提供类似 ext4 的只记录元数据的日志模式,同时这个插件还实现了元数据和内联校验和,并且可根据其挂载的时候所选择的 transaction model 来确定它所提供的 wandering logs 行为。

其它文件系统提供仅提供记录元数据日志的 ordered-mode journaling。尽管都能在崩溃后将文件系统恢复到正常状态,data-mode journaling 提供了最大程度的数据安全防护,但代价是性能有所降低,因为数据会被写两次(第一次到日志,第二次到磁盘)——而 Reiser4 通过 “wandering logs" 避免了这样的重复。可以根据数据的重要性选择文件系统。

Reiser4 是仅有的被设计成所有的操作都是完全 atomic 的同时还提供元数据和内联数据的校验和的文件系统——文件操作要么完全完成,要么就根本没有发生,所以不会因为操作执行到一半而导致数据损坏。因此它发生数据丢失的可能性相比其他文件系统要低得多。

基于 copy-on-write (也叫 write-anywhere)的文件系统,比如Reiser4、Btrfs 和 ZFS 不需要用传统的日志保护元数据,因为元数据永远不会被原地更新。虽然 Btrfs 还在使用日志树,但这个树仅仅是为了加快 fdatasync/fsync 的速度。

基于 FUSE 的文件系统[编辑 | 编辑源代码]

参考 FUSE

堆栈式文件系统[编辑 | 编辑源代码]

  • eCryptfs — The Enterprise Cryptographic Filesystem,一个 Linux 磁盘加密软件。它被设计为与POSIX兼容的文件系统级加密层,目标是在操作系统级别提供类似 GnuPG 的功能。
https://ecryptfs.org || ecryptfs-utils
  • mergerfs — 基于 FUSE 的联合文件系统。
https://github.com/trapexit/mergerfs || mergerfsAUR
  • mhddfs — 多机械硬盘 FUSE 文件系统, 基于 FUSE 的联合文件系统。
http://mhddfs.uvw.ru || mhddfsAUR
  • overlayfs — OverlayFS 是为 Linux 设计的联合文件系统服务,实现了联合挂载其他文件系统的功能。
https://docs.kernel.org/filesystems/overlayfs.html || linux
  • Unionfs:为 Linux、FreeBSD and NetBSD 设计的文件系统服务, 实现了联合挂载其他文件系统的功能。[5]
  • unionfs-fuse — Unionfs 的用户空间实现.
https://github.com/rpodgorny/unionfs-fuse || unionfs-fuse

只读文件系统[编辑 | 编辑源代码]

  • SquashFS — SquashFS 是一个压缩的只读文件系统,它压缩文件、inodes和目录,而且最高支持 1 MB 大小的 block 来实现更强力的压缩。
http://squashfs.sourceforge.net/ || squashfs-tools

集群文件系统[编辑 | 编辑源代码]

  • Ceph — 统一的分布式存储系统,旨在实现出色的性能,可靠性和可扩展性。
https://ceph.com/ || cephAUR
  • Glusterfs — 支持扩展到几PB的集群文件系统。
https://www.gluster.org/ || glusterfs
  • IPFS — 一种点对点超媒体协议,使网络更快,更安全,更开放。 IPFS旨在取代HTTP并为我们所有人构建更好的网络。 它使用 block 来存储文件的一部分,每个网络节点仅存储它感兴趣的内容,提供去重的、分布式的可扩展文件系统。 (alpha阶段)
https://ipfs.io/ || kubo
  • MooseFS — MooseFS 是一个容错、高可用性和高性能的向外扩展的扩展网络分布式文件系统。
https://moosefs.com || moosefs
  • OpenAFS — AFS分布式文件系统的开源实现
https://www.openafs.org || openafsAUR
  • OrangeFS:OrangeFS 是一个向外扩展的网络文件系统,为透明、并行地访问基于多个服务器的磁盘储存而设计。它为并行分布式应用提供了优化的 MPI-IO。它使 Linux 客户端、Windows、Hadoop 和 WebDAV 使用并列储存器变得简便。它与POSIX兼容,而且是 Linux kernel (4.6+)的一部分。[6]
  • Sheepdog:用于卷和容器服务的分布式对象存储系统,能智能地管理磁盘和节点。[7]
  • Tahoe-LAFS — Tahoe Least-Authority Filesystem 是一个免费、开放、安全、去中心化、容错、点对点的分布式 data store 和分布式文件系统。
https://tahoe-lafs.org/ || tahoe-lafsAUR

查看现有文件系统[编辑 | 编辑源代码]

lsblk 查看:

$ lsblk -f
NAME   FSTYPE LABEL     UUID                                 MOUNTPOINT
sdb                                                          
└─sdb1 vfat   Transcend 4A3C-A9E9

如果文件系统存在,那 FSTYPE 列会显示它的名字;如果它被mount了,挂载点会显示在 MOUNTPOINT 那一列。

创建文件系统[编辑 | 编辑源代码]

文件系统可以创建在一个分区上、逻辑容器如 LVMRAID,或者 dm-crypt 上或普通文件上(参考 Loop设备)。这里描述创建在分区上的情况。

注意: 文件系统可以直接写入到设备上,这样的设备叫做 superfloppy 或者 无分区磁盘。这样做会带来一些约束,特别是用它来 启动 系统。
警告:
  • 创建新文件系统之后,之前存放在该分区的数据会丢失且通常无法找回。请备份所有要保留的数据.
  • 某个分区用来干什么通常会限制能用什么文件系统,比如 EFI分区 就只能用 mkfs.vfat 创建的 FAT32,而包含 /boot 的分区的文件系统要考虑 boot loader 是否支持。

创建文件系统之前,目标分区必须处于未挂载状态。如果你要格式化的分区包含了一个已挂载的文件系统,在 lsblk 命令的 MOUNTPOINT 列中可以看到它。

$ lsblk -f
NAME   FSTYPE   LABEL       UUID                                 MOUNTPOINT
sda
├─sda1                      C4DA-2C4D                            
├─sda2 ext4                 5b1564b2-2e2c-452c-bcfa-d1f572ae99f2 /mnt
└─sda3                      56adc99b-a61e-46af-aab7-a6d07e504652 

你可以使用 umount 加上分区的挂载点来卸载这个文件系统:

# umount /mountpoint

查看挂载了的所有文件系统,参考#列出挂载的文件系统

mkfs(8) 创建新的文件系统,类型参见#文件系统类型。如果安装了其他特殊的工具,按照它们的说明来做。比如,以下命令在 /dev/sda1 上创建了一个 ext4 文件系统:

# mkfs.ext4 /dev/sda1

此外,你可以使用 mkfs。这是 mkfs.fstype 工具的统一入口。上面的命令等价于:

# mkfs -t ext4 /dev/sda1
提示:
  • mkfs.ext4 的时候可以用 -L 选项来给文件系统设置一个 标签e2label 用来对已经存在的文件系统改标签。
  • 文件系统在创建之后是有条件地 改变大小(resized)的。比如 XFS 可以扩容,但是不能缩小。参考 Resize capabilities

创建完成之后新的文件系统就可以挂载到某个目录了。

挂载文件系统[编辑 | 编辑源代码]

如果要手动挂载一个设备上的文件系统到某个目录,用 mount(8)。下面这个例子把 /dev/sda1 挂载到 /mnt

# mount /dev/sda1 /mnt

挂载之后,在 /mnt 下面就能看见 /dev/sda1 里面的内容。挂载之前 /mnt 文件夹里的内容在挂载之后将会变得不可见,直到 unmount 掉 /dev/sda1

fstab 描述了如果某个设备存在的话系统应该怎么自动挂载它。如果要修改 /etc/fstab,请阅读 fstab

如果 /etc/fstab 里描述了一个设备的挂载参数,而用 mount 时只给了设备名字或者挂载点,fstab 里的参数就会自动补上。比如,/etc/fstab 里指示 /dev/sda1 应该挂载到 /mnt,那下面的命令就会把 /dev/sda1 挂载到 /mnt,即使你没有显式指明:

# mount /dev/sda1

或者

# mount /mnt

mount 接受很多参数,这些参数依赖于文件系统是否支持。要改变这些参数的话,可以通过以下形式:

列出挂载的文件系统[编辑 | 编辑源代码]

findmnt(8) :

$ findmnt

findmnt 支持很多参数,可以利用它们来筛选输出或者获得更多信息。比如把某个挂载点或者设备作为参数,它就会只输出这个下面挂载了什么。

$ findmnt /dev/sda1

findmnt/etc/fstab/etc/mtab/proc/self/mounts 文件里收集信息。

卸载文件系统[编辑 | 编辑源代码]

umount(8) 来卸载文件系统。参数可以是包含文件系统的设备(比如/dev/sda1),也可以是挂载点(比如/mnt):

# umount /dev/sda1

或者

# umount /mnt

参阅[编辑 | 编辑源代码]